#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) { } mnd::Generator* MandelDevice::getGenerator(mnd::GeneratorType type) const { auto it = generators.find(type); if (it != generators.end()) return it->second.get(); else return nullptr; } MandelContext::MandelContext(void) { #if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) if (cpuInfo.hasAvx()) { auto fl = std::make_unique>(); auto db = std::make_unique>(); cpuGenerators.insert({ GeneratorType::FLOAT_AVX, std::move(fl) }); cpuGenerators.insert({ GeneratorType::DOUBLE_AVX512, std::move(db) }); } else if (cpuInfo.hasSse2()) { auto fl = std::make_unique>(); auto db = std::make_unique>(); cpuGenerators.insert({ GeneratorType::FLOAT_SSE2, std::move(fl) }); cpuGenerators.insert({ GeneratorType::DOUBLE_SSE2, std::move(db) }); } else #elif defined(__aarch64__) if (true) { auto fl = std::make_unique>(); auto db = std::make_unique>(); cpuGenerators.insert({ GeneratorType::FLOAT_NEON, std::move(fl) }); cpuGenerators.insert({ GeneratorType::DOUBLE_NEON, std::move(db) }); } else #endif { auto fl = std::make_unique>(); auto db = std::make_unique>(); cpuGenerators.insert({ GeneratorType::FLOAT, std::move(fl) }); cpuGenerators.insert({ GeneratorType::DOUBLE, std::move(db) }); } #ifdef WITH_BOOST auto quad = std::make_unique>(); auto oct = std::make_unique>(); cpuGenerators.insert({ GeneratorType::FLOAT128, std::move(quad) }); cpuGenerators.insert({ GeneratorType::FLOAT256, std::move(oct) }); #endif // WITH_BOOST #ifdef WITH_QD auto dd = std::make_unique>(); auto qd = std::make_unique>(); cpuGenerators.insert({ GeneratorType::DOUBLE_DOUBLE, std::move(dd) }); cpuGenerators.insert({ GeneratorType::DOUBLE_DOUBLE, std::move(qd) }); #endif // WITH_QD devices = createDevices(); adaptiveGenerator = createAdaptiveGenerator(); } std::unique_ptr MandelContext::createAdaptiveGenerator(void) { auto* floatGen = getCpuGenerator(GeneratorType::FLOAT); auto* doubleGen = getCpuGenerator(GeneratorType::DOUBLE); auto* doubleDoubleGen = getCpuGenerator(GeneratorType::DOUBLE_DOUBLE); auto* quadDoubleGen = getCpuGenerator(GeneratorType::QUAD_DOUBLE); auto* f256Gen = getCpuGenerator(GeneratorType::FLOAT256); if (cpuInfo.hasAvx()) { floatGen = getCpuGenerator(GeneratorType::FLOAT_AVX); doubleGen = getCpuGenerator(GeneratorType::DOUBLE_AVX); } else if (cpuInfo.hasSse2()) { floatGen = getCpuGenerator(GeneratorType::FLOAT_SSE2); doubleGen = getCpuGenerator(GeneratorType::DOUBLE_SSE2); } if (!devices.empty()) { auto& device = devices[0]; auto* fGen = device.getGenerator(GeneratorType::FLOAT); auto* dGen = device.getGenerator(GeneratorType::DOUBLE); auto* ddGen = device.getGenerator(GeneratorType::DOUBLE_DOUBLE); if (fGen) floatGen = fGen; if (dGen) doubleGen = dGen; if (ddGen) doubleDoubleGen = ddGen; } auto ag = std::make_unique(); ag->addGenerator(Precision::FLOAT, *floatGen); ag->addGenerator(Precision::DOUBLE, *doubleGen); ag->addGenerator(Precision::DOUBLE_DOUBLE, *doubleDoubleGen); ag->addGenerator(Precision::QUAD_DOUBLE, *quadDoubleGen); ag->addGenerator(Precision::FLOAT256, *f256Gen); return ag; } 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.generators.insert({ GeneratorType::FLOAT, std::make_unique(device) }); } catch (const std::string& err) { printf("err: %s", err.c_str()); } if (supportsDouble) { try { md.generators.insert({ GeneratorType::DOUBLE, std::make_unique(device) }); md.generators.insert({ GeneratorType::DOUBLE_DOUBLE, std::make_unique(device) }); } 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; } Generator& MandelContext::getDefaultGenerator(bool smooth) { return *adaptiveGenerator; } const std::vector& MandelContext::getDevices(void) { return devices; } Generator* MandelContext::getCpuGenerator(mnd::GeneratorType type) { auto it = cpuGenerators.find(type); if (it != cpuGenerators.end()) return it->second.get(); else return nullptr; }