#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::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>(); } 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>(); #endif devices = createDevices(); if (devices.empty()) { #ifdef WITH_BOOST adaptiveGenerator = std::make_unique( cpuGeneratorFloat.get(), cpuGeneratorDouble.get(), cpuGeneratorQuad.get()); adaptiveGeneratorSmooth = std::make_unique( cpuGeneratorFloatSmooth.get(), cpuGeneratorDoubleSmooth.get(), cpuGeneratorQuadSmooth.get()); #else adaptiveGenerator = std::make_unique( cpuGeneratorFloat.get(), cpuGeneratorDouble.get()); adaptiveGeneratorSmooth = std::make_unique( cpuGeneratorFloatSmooth.get(), cpuGeneratorDoubleSmooth.get()); #endif } else { auto& device1 = devices[0]; Generator* floatGenerator = device1.getGeneratorFloat(false); Generator* doubleGenerator = device1.getGeneratorDouble(false); Generator* floatGeneratorSmooth = device1.getGeneratorFloat(true); Generator* doubleGeneratorSmooth = device1.getGeneratorDouble(true); if (floatGenerator == nullptr) floatGenerator = cpuGeneratorFloat.get(); if (doubleGenerator == nullptr) doubleGenerator = cpuGeneratorDouble.get(); if (floatGeneratorSmooth == nullptr) floatGeneratorSmooth = cpuGeneratorFloatSmooth.get(); if (doubleGeneratorSmooth == nullptr) doubleGeneratorSmooth = cpuGeneratorDoubleSmooth.get(); #ifdef WITH_BOOST adaptiveGeneratorSmooth = std::make_unique(floatGeneratorSmooth, doubleGeneratorSmooth, cpuGeneratorDDSmooth.get()); adaptiveGenerator = std::make_unique(floatGenerator, doubleGenerator, cpuGeneratorDD.get()); #else adaptiveGeneratorSmooth = std::make_unique(floatGeneratorSmooth, doubleGeneratorSmooth); adaptiveGenerator = std::make_unique(floatGenerator, doubleGenerator); #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); } catch (const std::string& err) { } } 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(); }