#include "Mandel.h" #include "Fixed.h" #include "CpuGenerators.h" #include "ClGenerators.h" using mnd::MandelDevice; using mnd::MandelContext; using mnd::Generator; using mnd::AdaptiveGenerator; MandelContext mnd::initializeContext(void) { MandelContext context = MandelContext(); return context; } MandelDevice::MandelDevice(void) : floatGenerator{ nullptr }, doubleGenerator{ nullptr }, floatGeneratorSmooth{ nullptr }, doubleGeneratorSmooth{ nullptr } { } mnd::Generator* MandelDevice::getGeneratorFloat(bool smooth) const { if (smooth) return floatGeneratorSmooth.get(); else return floatGenerator.get(); } mnd::Generator* MandelDevice::getGeneratorDouble(bool smooth) const { if (smooth) return doubleGeneratorSmooth.get(); else return doubleGenerator.get(); } mnd::Generator* MandelDevice::getGeneratorDoubleDouble(bool smooth) const { if (smooth) return doubleDoubleGeneratorSmooth.get(); else return doubleDoubleGenerator.get(); } /* mnd::Generator* MandelDevice::getGeneratorQuad(bool smooth) const { if (smooth) return quadGeneratorSmooth.get(); else return quadGenerator.get(); }*/ /* mnd::Generator* MandelDevice::getGenerator128(bool smooth) const { if (smooth) return generator128Smooth.get(); else return generator128.get(); } */ MandelContext::MandelContext(void) : cpuGeneratorQuad{ nullptr }, cpuGeneratorQuadSmooth{ nullptr } { #if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) if (cpuInfo.hasAvx()) { cpuGeneratorFloat = std::make_unique>(); cpuGeneratorDouble = std::make_unique>(); cpuGeneratorFloatSmooth = std::make_unique>(); //cpuGeneratorDoubleSmooth = std::make_unique>(); cpuGeneratorDoubleSmooth = std::make_unique>(); } else if (cpuInfo.hasSse2()) { cpuGeneratorFloat = std::make_unique>(); cpuGeneratorDouble = std::make_unique>(); cpuGeneratorFloatSmooth = std::make_unique>(); cpuGeneratorDoubleSmooth = std::make_unique>(); } else #elif defined(__aarch64__) if (true) { cpuGeneratorFloat = std::make_unique>(); cpuGeneratorDouble = std::make_unique>(); cpuGeneratorFloatSmooth = std::make_unique>(); cpuGeneratorDoubleSmooth = std::make_unique>(); } else #endif { cpuGeneratorFloat = std::make_unique>(); cpuGeneratorDouble = std::make_unique>(); cpuGeneratorFloatSmooth = std::make_unique>(); cpuGeneratorDoubleSmooth = std::make_unique>(); } //cpuGenerator128Smooth = std::make_unique>(); //cpuGeneratorFixedp = std::make_unique>>(); #ifdef WITH_BOOST cpuGeneratorQuad = std::make_unique>(); cpuGeneratorQuadSmooth = std::make_unique>(); cpuGeneratorOct = std::make_unique>(); //cpuGenerator128 = std::make_unique>(); //cpuGenerator128Smooth = std::make_unique>(); #endif // WITH_BOOST #ifdef WITH_QD cpuGeneratorDD = std::make_unique>(); cpuGeneratorDDSmooth = std::make_unique>(); cpuGeneratorQD = std::make_unique>(); cpuGeneratorQDSmooth = std::make_unique>(); #endif devices = createDevices(); adaptiveGenerator = std::make_unique(); adaptiveGeneratorSmooth = std::make_unique(); { auto& device1 = devices[0]; Generator* floatGenerator = device1.getGeneratorFloat(false); Generator* doubleGenerator = device1.getGeneratorDouble(false); Generator* doubleDoubleGenerator = device1.getGeneratorDoubleDouble(false); Generator* floatGeneratorSmooth = device1.getGeneratorFloat(true); Generator* doubleGeneratorSmooth = device1.getGeneratorDouble(true); Generator* doubleDoubleGeneratorSmooth = device1.getGeneratorDoubleDouble(true); if (floatGenerator != nullptr) adaptiveGenerator->addGenerator(1.0e-7, *floatGenerator); else adaptiveGenerator->addGenerator(1.0e-7, *cpuGeneratorFloat); if (doubleGenerator != nullptr) adaptiveGenerator->addGenerator(0.5e-15, *doubleGenerator); else adaptiveGenerator->addGenerator(0.5e-15, *cpuGeneratorDouble); if (floatGeneratorSmooth != nullptr) adaptiveGeneratorSmooth->addGenerator(1.0e-7, *floatGeneratorSmooth); else adaptiveGeneratorSmooth->addGenerator(1.0e-7, *cpuGeneratorFloatSmooth); if (doubleGeneratorSmooth != nullptr) adaptiveGeneratorSmooth->addGenerator(0.5e-15, *doubleGeneratorSmooth); else adaptiveGeneratorSmooth->addGenerator(0.5e-15, *cpuGeneratorDoubleSmooth); if (doubleDoubleGenerator != nullptr) adaptiveGenerator->addGenerator(Real("1.0e-29"), *doubleDoubleGenerator); if (doubleDoubleGeneratorSmooth != nullptr) adaptiveGeneratorSmooth->addGenerator(Real("1.0e-29"), *doubleDoubleGeneratorSmooth); } #ifdef WITH_QD adaptiveGenerator->addGenerator(Real("1.0e-29"), *cpuGeneratorDD); adaptiveGeneratorSmooth->addGenerator(Real("1.0e-29"), *cpuGeneratorDDSmooth); adaptiveGenerator->addGenerator(Real("1.0e-57"), *cpuGeneratorQD); adaptiveGeneratorSmooth->addGenerator(Real("1.0e-57"), *cpuGeneratorQDSmooth); #endif #ifdef WITH_BOOST //adaptiveGenerator->addGenerator(1.0e-28, *cpuGeneratorQuad); //adaptiveGeneratorSmooth->addGenerator(1.0e-28, *cpuGeneratorQuadSmooth); #endif } std::vector MandelContext::createDevices(void) { std::vector mandelDevices; #ifdef WITH_OPENCL std::vector platforms; cl::Platform::get(&platforms); //platforms.erase(platforms.begin() + 1); for (auto& platform : platforms) { std::string name = platform.getInfo(); std::string profile = platform.getInfo(); //std::string ext = platform.getInfo(); //printf("Platform extensions: %s\n", ext.c_str()); //printf("Platform: %s, %s\n", name.c_str(), profile.c_str()); std::vector devices; platform.getDevices(CL_DEVICE_TYPE_GPU, &devices); for (auto& device : devices) { //printf("Device: %s\n", device.getInfo().c_str()); //printf("preferred float width: %d\n", device.getInfo()); //printf("vendor: %s\n", device.getInfo().c_str()); std::string extensions = device.getInfo(); auto supportsDouble = extensions.find("cl_khr_fp64") != std::string::npos; //printf("Device extensions: %s\n", ext.c_str()); MandelDevice md; //printf("clock: %d", device.getInfo()); md.name = device.getInfo(); md.vendor = device.getInfo(); try { md.floatGenerator = std::make_unique(device, false); md.floatGeneratorSmooth = std::make_unique(device, true); } catch (const std::string& err) { printf("err: %s", err.c_str()); } if (supportsDouble) { try { md.doubleGenerator = std::make_unique(device, false); md.doubleGeneratorSmooth = std::make_unique(device, true); md.doubleDoubleGenerator = std::make_unique(device, false); md.doubleDoubleGeneratorSmooth = std::make_unique(device, true); } catch (const std::string& err) { printf("err: %s", err.c_str()); fflush(stdout); } } try { //md.generator128 = std::make_unique(device); } catch (const std::string& err) { //fprintf(stderr, "error creating 128bit cl generator: %s\n", err.c_str()); } mandelDevices.push_back(std::move(md)); } } #endif // WITH_OPENCL return mandelDevices; } const std::string& MandelDevice::getName(void) const { return name; } Generator& MandelContext::getDefaultGenerator(bool smooth) { if (smooth) return *adaptiveGeneratorSmooth; else return *adaptiveGenerator; } const std::vector& MandelContext::getDevices(void) { return devices; } Generator& MandelContext::getCpuGeneratorFloat(void) { return *cpuGeneratorFloat; } Generator& MandelContext::getCpuGeneratorDouble(void) { return *cpuGeneratorDouble; } Generator* MandelContext::getCpuGeneratorQuad(void) { return cpuGeneratorQuad.get(); } Generator* MandelContext::getCpuGeneratorOct(void) { return cpuGeneratorOct.get(); } Generator* MandelContext::getCpuGenerator128(void) { return cpuGenerator128.get(); } Generator* MandelContext::getCpuGeneratorDD(void) { return cpuGeneratorDD.get(); } Generator* MandelContext::getCpuGeneratorQD(void) { return cpuGeneratorQD.get(); }