Mandel.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. #include "Mandel.h"
  2. #include "Fixed.h"
  3. #include "CpuGenerators.h"
  4. #include "ClGenerators.h"
  5. using mnd::MandelDevice;
  6. using mnd::MandelContext;
  7. using mnd::Generator;
  8. using mnd::AdaptiveGenerator;
  9. MandelContext mnd::initializeContext(void)
  10. {
  11. MandelContext context = MandelContext();
  12. return context;
  13. }
  14. MandelDevice::MandelDevice(void)
  15. {
  16. }
  17. mnd::Generator* MandelDevice::getGenerator(mnd::GeneratorType type) const
  18. {
  19. auto it = generators.find(type);
  20. if (it != generators.end())
  21. return it->second.get();
  22. else
  23. return nullptr;
  24. }
  25. std::vector<mnd::GeneratorType> MandelDevice::getSupportedTypes(void) const
  26. {
  27. std::vector<GeneratorType> types;
  28. for (auto& [type, gen] : generators) {
  29. types.push_back(type);
  30. }
  31. return types;
  32. }
  33. MandelContext::MandelContext(void)
  34. {
  35. #if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)
  36. if (cpuInfo.hasAvx()) {
  37. //auto fl = std::make_unique<CpuGenerator<float, mnd::X86_AVX, true>>();
  38. auto fl = std::make_unique<CpuGenerator<float, mnd::X86_AVX, true>>();
  39. auto db = std::make_unique<CpuGenerator<double, mnd::X86_AVX, true>>();
  40. cpuGenerators.insert({ GeneratorType::FLOAT_AVX, std::move(fl) });
  41. cpuGenerators.insert({ GeneratorType::DOUBLE_AVX, std::move(db) });
  42. if (cpuInfo.hasFma()) {
  43. auto ddavx = std::make_unique<CpuGenerator<DoubleDouble, mnd::X86_AVX_FMA, true>>();
  44. cpuGenerators.insert({ GeneratorType::DOUBLE_DOUBLE_AVX, std::move(ddavx) });
  45. }
  46. }
  47. if (cpuInfo.hasSse2()) {
  48. auto fl = std::make_unique<CpuGenerator<float, mnd::X86_SSE2, true>>();
  49. auto db = std::make_unique<CpuGenerator<double, mnd::X86_SSE2, true>>();
  50. cpuGenerators.insert({ GeneratorType::FLOAT_SSE2, std::move(fl) });
  51. cpuGenerators.insert({ GeneratorType::DOUBLE_SSE2, std::move(db) });
  52. }
  53. #elif defined(__aarch64__)
  54. if (cpuInfo.hasNeon()) {
  55. auto fl = std::make_unique<CpuGenerator<float, mnd::ARM_NEON, true>>();
  56. auto db = std::make_unique<CpuGenerator<double, mnd::ARM_NEON, true>>();
  57. cpuGenerators.insert({ GeneratorType::FLOAT_NEON, std::move(fl) });
  58. cpuGenerators.insert({ GeneratorType::DOUBLE_NEON, std::move(db) });
  59. }
  60. #endif
  61. {
  62. auto fl = std::make_unique<CpuGenerator<float, mnd::NONE, true>>();
  63. auto db = std::make_unique<CpuGenerator<double, mnd::NONE, true>>();
  64. cpuGenerators.insert({ GeneratorType::FLOAT, std::move(fl) });
  65. cpuGenerators.insert({ GeneratorType::DOUBLE, std::move(db) });
  66. }
  67. #ifdef WITH_BOOST
  68. auto quad = std::make_unique<CpuGenerator<Float128, mnd::NONE, true>>();
  69. auto oct = std::make_unique<CpuGenerator<Float256, mnd::NONE, true>>();
  70. cpuGenerators.insert({ GeneratorType::FLOAT128, std::move(quad) });
  71. cpuGenerators.insert({ GeneratorType::FLOAT256, std::move(oct) });
  72. #endif // WITH_BOOST
  73. #ifdef WITH_QD
  74. auto dd = std::make_unique<CpuGenerator<DoubleDouble, mnd::NONE, true>>();
  75. auto qd = std::make_unique<CpuGenerator<QuadDouble, mnd::NONE, true>>();
  76. cpuGenerators.insert({ GeneratorType::DOUBLE_DOUBLE, std::move(dd) });
  77. cpuGenerators.insert({ GeneratorType::QUAD_DOUBLE, std::move(qd) });
  78. #endif // WITH_QD
  79. auto fix512 = std::make_unique<CpuGenerator<Fixed512, mnd::NONE, true>>();
  80. cpuGenerators.insert({ GeneratorType::FIXED512, std::move(fix512) });
  81. devices = createDevices();
  82. adaptiveGenerator = createAdaptiveGenerator();
  83. }
  84. std::unique_ptr<mnd::AdaptiveGenerator> MandelContext::createAdaptiveGenerator(void)
  85. {
  86. auto* floatGen = getCpuGenerator(GeneratorType::FLOAT);
  87. auto* doubleGen = getCpuGenerator(GeneratorType::DOUBLE);
  88. auto* doubleDoubleGen = getCpuGenerator(GeneratorType::DOUBLE_DOUBLE);
  89. auto* quadDoubleGen = getCpuGenerator(GeneratorType::QUAD_DOUBLE);
  90. auto* f256Gen = getCpuGenerator(GeneratorType::FLOAT256);
  91. if (cpuInfo.hasAvx()) {
  92. floatGen = getCpuGenerator(GeneratorType::FLOAT_AVX);
  93. doubleGen = getCpuGenerator(GeneratorType::DOUBLE_AVX);
  94. }
  95. else if (cpuInfo.hasSse2()) {
  96. floatGen = getCpuGenerator(GeneratorType::FLOAT_SSE2);
  97. doubleGen = getCpuGenerator(GeneratorType::DOUBLE_SSE2);
  98. }
  99. if (!devices.empty()) {
  100. auto& device = devices[0];
  101. auto* fGen = device.getGenerator(GeneratorType::FLOAT);
  102. auto* dGen = device.getGenerator(GeneratorType::DOUBLE);
  103. auto* ddGen = device.getGenerator(GeneratorType::DOUBLE_DOUBLE);
  104. if (fGen)
  105. floatGen = fGen;
  106. if (dGen)
  107. doubleGen = dGen;
  108. if (ddGen)
  109. doubleDoubleGen = ddGen;
  110. }
  111. auto ag = std::make_unique<AdaptiveGenerator>();
  112. ag->addGenerator(Precision::FLOAT, *floatGen);
  113. ag->addGenerator(Precision::DOUBLE, *doubleGen);
  114. ag->addGenerator(Precision::DOUBLE_DOUBLE, *doubleDoubleGen);
  115. ag->addGenerator(Precision::QUAD_DOUBLE, *quadDoubleGen);
  116. ag->addGenerator(Precision::FLOAT256, *f256Gen);
  117. ag->addGenerator(Precision::INF_PREC, *f256Gen);
  118. return ag;
  119. }
  120. std::vector<MandelDevice> MandelContext::createDevices(void)
  121. {
  122. std::vector<MandelDevice> mandelDevices;
  123. #ifdef WITH_OPENCL
  124. std::vector<cl::Platform> platforms;
  125. cl::Platform::get(&platforms);
  126. //platforms.erase(platforms.begin() + 1);
  127. for (auto& platform : platforms) {
  128. std::string name = platform.getInfo<CL_PLATFORM_NAME>();
  129. std::string profile = platform.getInfo<CL_PLATFORM_PROFILE>();
  130. printf("using opencl platform: %s\n", name.c_str());
  131. //std::string ext = platform.getInfo<CL_PLATFORM_EXTENSIONS>();
  132. //printf("Platform extensions: %s\n", ext.c_str());
  133. //printf("Platform: %s, %s\n", name.c_str(), profile.c_str());
  134. std::vector<cl::Device> devices;
  135. platform.getDevices(CL_DEVICE_TYPE_GPU | CL_DEVICE_TYPE_CPU, &devices);
  136. for (auto& device : devices) {
  137. //printf("Device: %s\n", device.getInfo<CL_DEVICE_NAME>().c_str());
  138. //printf("preferred float width: %d\n", device.getInfo<CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT>());
  139. //printf("vendor: %s\n", device.getInfo<CL_DEVICE_VENDOR>().c_str());
  140. std::string extensions = device.getInfo<CL_DEVICE_EXTENSIONS>();
  141. auto supportsDouble = extensions.find("cl_khr_fp64") != std::string::npos;
  142. //printf("Device extensions: %s\n", ext.c_str());
  143. MandelDevice md;
  144. //printf("clock: %d", device.getInfo<CL_DEVICE_MAX_CLOCK_FREQUENCY>());
  145. md.name = device.getInfo<CL_DEVICE_NAME>();
  146. md.vendor = device.getInfo<CL_DEVICE_VENDOR>();
  147. printf(" using opencl device: %s\n", md.name.c_str());
  148. try {
  149. md.generators.insert({ GeneratorType::FLOAT, std::make_unique<ClGeneratorFloat>(device) });
  150. }
  151. catch (const std::string& err) {
  152. printf("err: %s", err.c_str());
  153. }
  154. if (supportsDouble) {
  155. try {
  156. md.generators.insert({ GeneratorType::DOUBLE, std::make_unique<ClGeneratorDouble>(device) });
  157. md.generators.insert({ GeneratorType::DOUBLE_DOUBLE, std::make_unique<ClGeneratorDoubleDouble>(device) });
  158. md.generators.insert({ GeneratorType::QUAD_DOUBLE, std::make_unique<ClGeneratorQuadDouble>(device) });
  159. }
  160. catch (const std::string& err) {
  161. printf("err: %s", err.c_str());
  162. fflush(stdout);
  163. }
  164. }
  165. try {
  166. //md.generator128 = std::make_unique<ClGenerator128>(device);
  167. }
  168. catch (const std::string& err) {
  169. //fprintf(stderr, "error creating 128bit cl generator: %s\n", err.c_str());
  170. }
  171. mandelDevices.push_back(std::move(md));
  172. }
  173. }
  174. #endif // WITH_OPENCL
  175. return mandelDevices;
  176. }
  177. AdaptiveGenerator& MandelContext::getDefaultGenerator(void)
  178. {
  179. return *adaptiveGenerator;
  180. }
  181. const std::vector<MandelDevice>& MandelContext::getDevices(void)
  182. {
  183. return devices;
  184. }
  185. Generator* MandelContext::getCpuGenerator(mnd::GeneratorType type)
  186. {
  187. auto it = cpuGenerators.find(type);
  188. if (it != cpuGenerators.end())
  189. return it->second.get();
  190. else
  191. return nullptr;
  192. }
  193. std::vector<mnd::GeneratorType> MandelContext::getSupportedTypes(void) const
  194. {
  195. std::vector<GeneratorType> types;
  196. for (auto& [type, gen] : cpuGenerators) {
  197. types.push_back(type);
  198. }
  199. return types;
  200. }