Esempio n. 1
0
/**
 * 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;
}
Esempio n. 2
0
/**
 * 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;
}