Mandel.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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. floatGenerator{ nullptr },
  16. doubleGenerator{ nullptr },
  17. floatGeneratorSmooth{ nullptr },
  18. doubleGeneratorSmooth{ nullptr }
  19. {
  20. }
  21. mnd::Generator* MandelDevice::getGeneratorFloat(bool smooth) const
  22. {
  23. if (smooth)
  24. return floatGeneratorSmooth.get();
  25. else
  26. return floatGenerator.get();
  27. }
  28. mnd::Generator* MandelDevice::getGeneratorDouble(bool smooth) const
  29. {
  30. if (smooth)
  31. return doubleGeneratorSmooth.get();
  32. else
  33. return doubleGenerator.get();
  34. }
  35. /*
  36. mnd::Generator* MandelDevice::getGeneratorQuad(bool smooth) const
  37. {
  38. if (smooth)
  39. return quadGeneratorSmooth.get();
  40. else
  41. return quadGenerator.get();
  42. }*/
  43. /*
  44. mnd::Generator* MandelDevice::getGenerator128(bool smooth) const
  45. {
  46. if (smooth)
  47. return generator128Smooth.get();
  48. else
  49. return generator128.get();
  50. }
  51. */
  52. MandelContext::MandelContext(void) :
  53. cpuGeneratorQuad{ nullptr },
  54. cpuGeneratorQuadSmooth{ nullptr }
  55. {
  56. #if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)
  57. if (cpuInfo.hasAvx()) {
  58. cpuGeneratorFloat = std::make_unique<CpuGenerator<float, mnd::X86_AVX, true, false>>();
  59. cpuGeneratorDouble = std::make_unique<CpuGenerator<double, mnd::X86_AVX, true, false>>();
  60. cpuGeneratorFloatSmooth = std::make_unique<CpuGenerator<float, mnd::X86_AVX, true, true>>();
  61. //cpuGeneratorDoubleSmooth = std::make_unique<CpuGenerator<double, mnd::X86_AVX, true, true>>();
  62. cpuGeneratorDoubleSmooth = std::make_unique<CpuGenerator<double, mnd::NONE, true, true>>();
  63. }
  64. else if (cpuInfo.hasSse2()) {
  65. cpuGeneratorFloat = std::make_unique<CpuGenerator<float, mnd::X86_SSE2, true, false>>();
  66. cpuGeneratorDouble = std::make_unique<CpuGenerator<double, mnd::X86_SSE2, true, false>>();
  67. cpuGeneratorFloatSmooth = std::make_unique<CpuGenerator<float, mnd::X86_SSE2, true, true>>();
  68. cpuGeneratorDoubleSmooth = std::make_unique<CpuGenerator<double, mnd::X86_SSE2, true, true>>();
  69. }
  70. else
  71. #elif defined(__aarch64__)
  72. if (true) {
  73. cpuGeneratorFloat = std::make_unique<CpuGenerator<float, mnd::ARM_NEON, true, false>>();
  74. cpuGeneratorDouble = std::make_unique<CpuGenerator<double, mnd::ARM_NEON, true, false>>();
  75. cpuGeneratorFloatSmooth = std::make_unique<CpuGenerator<float, mnd::ARM_NEON>>();
  76. cpuGeneratorDoubleSmooth = std::make_unique<CpuGenerator<double, mnd::ARM_NEON>>();
  77. }
  78. else
  79. #endif
  80. {
  81. cpuGeneratorFloat = std::make_unique<CpuGenerator<float, mnd::NONE, true, false>>();
  82. cpuGeneratorDouble = std::make_unique<CpuGenerator<double, mnd::NONE, true, false>>();
  83. cpuGeneratorFloatSmooth = std::make_unique<CpuGenerator<float, mnd::NONE, true, true>>();
  84. cpuGeneratorDoubleSmooth = std::make_unique<CpuGenerator<double, mnd::NONE, true, true>>();
  85. }
  86. //cpuGenerator128Smooth = std::make_unique<CpuGenerator<Fixed128>>();
  87. //cpuGeneratorFixedp = std::make_unique<CpuGenerator<fixed<1, 3>>>();
  88. #ifdef WITH_BOOST
  89. cpuGeneratorQuad = std::make_unique<CpuGenerator<Float128, mnd::NONE, true, false>>();
  90. cpuGeneratorQuadSmooth = std::make_unique<CpuGenerator<Float128, mnd::NONE, true, true>>();
  91. cpuGeneratorOct = std::make_unique<CpuGenerator<Float256, mnd::NONE, true, false>>();
  92. //cpuGenerator128 = std::make_unique<CpuGenerator<Fixed128, mnd::NONE, true, false>>();
  93. //cpuGenerator128Smooth = std::make_unique<CpuGenerator<Fixed128, mnd::NONE, true, true>>();
  94. #endif // WITH_BOOST
  95. #ifdef WITH_QD
  96. cpuGeneratorDD = std::make_unique<CpuGenerator<DoubleDouble, mnd::NONE, true, false>>();
  97. cpuGeneratorDDSmooth = std::make_unique<CpuGenerator<DoubleDouble, mnd::NONE, true, true>>();
  98. cpuGeneratorQD = std::make_unique<CpuGenerator<QuadDouble, mnd::NONE, true, false>>();
  99. cpuGeneratorQDSmooth = std::make_unique<CpuGenerator<QuadDouble, mnd::NONE, true, true>>();
  100. #endif
  101. devices = createDevices();
  102. adaptiveGenerator = std::make_unique<AdaptiveGenerator>();
  103. adaptiveGeneratorSmooth = std::make_unique<AdaptiveGenerator>();
  104. adaptiveGenerator->addGenerator(1.0e-7, *cpuGeneratorFloat);
  105. adaptiveGenerator->addGenerator(0.5e-15, *cpuGeneratorDouble);
  106. adaptiveGeneratorSmooth->addGenerator(1.0e-7, *cpuGeneratorFloatSmooth);
  107. adaptiveGeneratorSmooth->addGenerator(0.5e-15, *cpuGeneratorDoubleSmooth);
  108. {
  109. auto& device1 = devices[0];
  110. Generator* floatGenerator = device1.getGeneratorFloat(false);
  111. Generator* doubleGenerator = device1.getGeneratorDouble(false);
  112. Generator* floatGeneratorSmooth = device1.getGeneratorFloat(true);
  113. Generator* doubleGeneratorSmooth = device1.getGeneratorDouble(true);
  114. if (floatGenerator != nullptr)
  115. adaptiveGenerator->addGenerator(1.0e-7, *floatGenerator);
  116. if (doubleGenerator != nullptr)
  117. adaptiveGenerator->addGenerator(0.5e-15, *doubleGenerator);
  118. if (floatGeneratorSmooth != nullptr)
  119. adaptiveGeneratorSmooth->addGenerator(1.0e-7, *floatGeneratorSmooth);
  120. if (doubleGeneratorSmooth != nullptr)
  121. adaptiveGeneratorSmooth->addGenerator(0.5e-15, *doubleGeneratorSmooth);
  122. }
  123. #ifdef WITH_QD
  124. adaptiveGenerator->addGenerator(Real("1.0e-29"), *cpuGeneratorDD);
  125. adaptiveGeneratorSmooth->addGenerator(Real("1.0e-29"), *cpuGeneratorDDSmooth);
  126. adaptiveGenerator->addGenerator(Real("1.0e-50"), *cpuGeneratorQD);
  127. adaptiveGeneratorSmooth->addGenerator(Real("1.0e-50"), *cpuGeneratorQDSmooth);
  128. #endif
  129. #ifdef WITH_BOOST
  130. //adaptiveGenerator->addGenerator(1.0e-28, *cpuGeneratorQuad);
  131. //adaptiveGeneratorSmooth->addGenerator(1.0e-28, *cpuGeneratorQuadSmooth);
  132. #endif
  133. }
  134. std::vector<MandelDevice> MandelContext::createDevices(void)
  135. {
  136. std::vector<MandelDevice> mandelDevices;
  137. #ifdef WITH_OPENCL
  138. std::vector<cl::Platform> platforms;
  139. cl::Platform::get(&platforms);
  140. //platforms.erase(platforms.begin() + 1);
  141. for (auto& platform : platforms) {
  142. std::string name = platform.getInfo<CL_PLATFORM_NAME>();
  143. std::string profile = platform.getInfo<CL_PLATFORM_PROFILE>();
  144. //std::string ext = platform.getInfo<CL_PLATFORM_EXTENSIONS>();
  145. //printf("Platform extensions: %s\n", ext.c_str());
  146. //printf("Platform: %s, %s\n", name.c_str(), profile.c_str());
  147. std::vector<cl::Device> devices;
  148. platform.getDevices(CL_DEVICE_TYPE_GPU, &devices);
  149. for (auto& device : devices) {
  150. //printf("Device: %s\n", device.getInfo<CL_DEVICE_NAME>().c_str());
  151. //printf("preferred float width: %d\n", device.getInfo<CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT>());
  152. //printf("vendor: %s\n", device.getInfo<CL_DEVICE_VENDOR>().c_str());
  153. std::string extensions = device.getInfo<CL_DEVICE_EXTENSIONS>();
  154. auto supportsDouble = extensions.find("cl_khr_fp64") != std::string::npos;
  155. //printf("Device extensions: %s\n", ext.c_str());
  156. MandelDevice md;
  157. //printf("clock: %d", device.getInfo<CL_DEVICE_MAX_CLOCK_FREQUENCY>());
  158. md.name = device.getInfo<CL_DEVICE_NAME>();
  159. md.vendor = device.getInfo<CL_DEVICE_VENDOR>();
  160. try {
  161. md.floatGenerator = std::make_unique<ClGeneratorFloat>(device, false);
  162. md.floatGeneratorSmooth = std::make_unique<ClGeneratorFloat>(device, true);
  163. }
  164. catch (const std::string& err) {
  165. printf("err: %s", err.c_str());
  166. }
  167. if (supportsDouble) {
  168. try {
  169. md.doubleGenerator = std::make_unique<ClGeneratorDouble>(device, false);
  170. md.doubleGeneratorSmooth = std::make_unique<ClGeneratorDouble>(device, true);
  171. }
  172. catch (const std::string& err) {
  173. }
  174. }
  175. try {
  176. //md.generator128 = std::make_unique<ClGenerator128>(device);
  177. }
  178. catch (const std::string& err) {
  179. //fprintf(stderr, "error creating 128bit cl generator: %s\n", err.c_str());
  180. }
  181. mandelDevices.push_back(std::move(md));
  182. }
  183. }
  184. #endif // WITH_OPENCL
  185. return mandelDevices;
  186. }
  187. const std::string& MandelDevice::getName(void) const
  188. {
  189. return name;
  190. }
  191. Generator& MandelContext::getDefaultGenerator(bool smooth)
  192. {
  193. if (smooth)
  194. return *adaptiveGeneratorSmooth;
  195. else
  196. return *adaptiveGenerator;
  197. }
  198. const std::vector<MandelDevice>& MandelContext::getDevices(void)
  199. {
  200. return devices;
  201. }
  202. Generator& MandelContext::getCpuGeneratorFloat(void)
  203. {
  204. return *cpuGeneratorFloat;
  205. }
  206. Generator& MandelContext::getCpuGeneratorDouble(void)
  207. {
  208. return *cpuGeneratorDouble;
  209. }
  210. Generator* MandelContext::getCpuGeneratorQuad(void)
  211. {
  212. return cpuGeneratorQuad.get();
  213. }
  214. Generator* MandelContext::getCpuGeneratorOct(void)
  215. {
  216. return cpuGeneratorOct.get();
  217. }
  218. Generator* MandelContext::getCpuGenerator128(void)
  219. {
  220. return cpuGenerator128.get();
  221. }
  222. Generator* MandelContext::getCpuGeneratorDD(void)
  223. {
  224. return cpuGeneratorDD.get();
  225. }
  226. Generator* MandelContext::getCpuGeneratorQD(void)
  227. {
  228. return cpuGeneratorQD.get();
  229. }