Mandel.cpp 7.2 KB

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