Mandel.cpp 10 KB

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