/** * If VEXCL_CACHE_KERNELS macro is defined, then program binaries are cached * in filesystem and reused in the following runs. */ inline cl::Program build_sources( const cl::CommandQueue &queue, const std::string &source, const std::string &options = "" ) { #ifdef VEXCL_SHOW_KERNELS std::cout << source << std::endl; #else if (getenv("VEXCL_SHOW_KERNELS")) std::cout << source << std::endl; #endif auto context = queue.getInfo<CL_QUEUE_CONTEXT>(); auto device = context.getInfo<CL_CONTEXT_DEVICES>(); std::string compile_options = options + " " + get_compile_options(queue); #ifdef VEXCL_CACHE_KERNELS // Get unique (hopefully) hash string for the kernel. std::ostringstream compiler_tag; compiler_tag #if defined(_MSC_VER) << "MSC " << _MSC_VER #elif defined(__clang__) << "Clang " << __clang_major__ << "." << __clang_minor__ #elif defined(__GNUC__) << "g++ " << __GNUC__ << "." << __GNUC_MINOR__ #else << "unknown" #endif ; sha1_hasher sha1; sha1.process(source) .process(cl::Platform(device[0].getInfo<CL_DEVICE_PLATFORM>()).getInfo<CL_PLATFORM_NAME>()) .process(device[0].getInfo<CL_DEVICE_NAME>()) .process(compile_options) .process(compiler_tag.str()) ; std::string hash = static_cast<std::string>(sha1); // Try to get cached program binaries: try { if (boost::optional<cl::Program> program = load_program_binaries(hash, context, device, compile_options)) return *program; } catch (...) { // Shit happens. std::cerr << "Failed to load precompiled binaries" << std::endl; } #endif // If cache is not available, just compile the sources. cl::Program program(context, source); try { program.build(device, (options + " " + get_compile_options(queue)).c_str()); } catch(const cl::Error&) { std::cerr << source << std::endl << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device[0]) << std::endl; vex::detail::print_backtrace(); throw; } #ifdef VEXCL_CACHE_KERNELS // Save program binaries for future reuse: save_program_binaries(hash, program); #endif return program; }
/** * If VEXCL_CACHE_KERNELS macro is defined, then program binaries are cached * in filesystem and reused in the following runs. */ inline cl::Program build_sources( const cl::CommandQueue &queue, const std::string &source, const std::string &options = "" ) { #ifdef VEXCL_SHOW_KERNELS std::cout << source << std::endl; #else # ifdef _MSC_VER # pragma warning(push) # pragma warning(disable: 4996) # endif if (getenv("VEXCL_SHOW_KERNELS")) std::cout << source << std::endl; # ifdef _MSC_VER # pragma warning(pop) # endif #endif auto context = queue.getInfo<CL_QUEUE_CONTEXT>(); auto device = context.getInfo<CL_CONTEXT_DEVICES>(); std::string compile_options = options + " " + get_compile_options(queue); #ifdef VEXCL_CACHE_KERNELS // Get unique (hopefully) hash string for the kernel. std::ostringstream fullsrc; fullsrc << "// Platform: " << cl::Platform(device[0].getInfo<CL_DEVICE_PLATFORM>()).getInfo<CL_PLATFORM_NAME>() << "\n// Device: " << device[0].getInfo<CL_DEVICE_NAME>() << "\n// Compiler: " #if defined(_MSC_VER) << "MSC " << _MSC_VER #elif defined(__clang__) << "Clang " << __clang_major__ << "." << __clang_minor__ #elif defined(__GNUC__) << "g++ " << __GNUC__ << "." << __GNUC_MINOR__ #else << "unknown" #endif << "\n// options: " << compile_options << "\n" << source; std::string hash = sha1( fullsrc.str() ); // Try to get cached program binaries: try { if (boost::optional<cl::Program> program = load_program_binaries(hash, context, device)) return *program; } catch (...) { // Shit happens. } #endif // If cache is not available, just compile the sources. cl::Program program(context, cl::Program::Sources( 1, std::make_pair(source.c_str(), source.size()) )); try { program.build(device, (options + " " + get_compile_options(queue)).c_str()); } catch(const cl::Error&) { std::cerr << source << std::endl << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device[0]) << std::endl; throw; } #ifdef VEXCL_CACHE_KERNELS // Save program binaries for future reuse: save_program_binaries(hash, program, fullsrc.str()); #endif return program; }