Example #1
0
/// Tries to read program binaries from file cache.
inline boost::optional<cl::Program> load_program_binaries(
        const std::string &hash, const cl::Context &context,
        const std::vector<cl::Device> &device,
        const std::string &options = ""
        )
{
    std::ifstream bfile(program_binaries_path(hash) + "kernel", std::ios::binary);
    if (!bfile) return boost::optional<cl::Program>();

    size_t n;
    std::vector<char> buf;

    bfile.read((char*)&n, sizeof(size_t));
    buf.resize(n);
    bfile.read(buf.data(), n);

    cl::Program program(context, device, cl::Program::Binaries(
                 1, std::make_pair(static_cast<const void*>(buf.data()), n)));

    try {
        program.build(device, options.c_str());
    } catch(const cl::Error&) {
        std::cerr << "Loading binaries failed:" << std::endl
            << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device[0])
            << std::endl;
        return boost::optional<cl::Program>();
    }

    return boost::optional<cl::Program>(program);
}
Example #2
0
/// Compile and load a program from source string.
inline vex::backend::program build_sources(const command_queue &q,
        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

    std::string compile_options = options + " " + get_compile_options(q);

    sha1_hasher sha1;
    sha1.process(source)
        .process(compile_options)
        .process(VEXCL_JIT_COMPILER)
        .process(VEXCL_JIT_COMPILER_OPTIONS);

    std::string hash = static_cast<std::string>(sha1);

    // Write source to a .cpp file
    std::string basename = program_binaries_path(hash, true) + "kernel";
    std::string sofile   = basename + ".so";

    if ( !boost::filesystem::exists(sofile) ) {
        std::string cppfile = basename + ".cpp";

        {
            std::ofstream f(cppfile);
            f << source;
        }

        // Compile the source.
        std::ostringstream cmdline;
        cmdline << VEXCL_JIT_COMPILER << " -o " << sofile << " " << cppfile << " "
                << VEXCL_JIT_COMPILER_OPTIONS << " " << compile_options;

        if (0 != system(cmdline.str().c_str()) ) {
#ifndef VEXCL_SHOW_KERNELS
            std::cerr << source << std::endl;
#endif

            vex::detail::print_backtrace();
            throw std::runtime_error("Kernel compilation failed");
        }
    }

    // Load the compiled shared library.
    return boost::dll::shared_library(sofile);
}
Example #3
0
/// Saves program binaries for future reuse.
inline void save_program_binaries(
        const std::string &hash, const cl::Program &program, const std::string &source
        )
{
    std::ofstream bfile(program_binaries_path(hash, true) + "kernel", std::ios::binary);
    if (!bfile) return;

    std::vector<size_t> sizes    = program.getInfo<CL_PROGRAM_BINARY_SIZES>();
    std::vector<char*>  binaries = program.getInfo<CL_PROGRAM_BINARIES>();

    assert(sizes.size() == 1);

    bfile.write((char*)&sizes[0], sizeof(size_t));
    bfile.write(binaries[0], sizes[0]);
    delete[] binaries[0];

    bfile << "\n" << source << "\n";
}
Example #4
0
/// Saves program binaries for future reuse.
inline void save_program_binaries(
        const std::string &hash, const cl::Program &program
        )
{
    // Prevent writing to the same file by several threads at the same time.
    static boost::mutex mx;
    boost::lock_guard<boost::mutex> lock(mx);

    std::ofstream bfile(program_binaries_path(hash, true) + "kernel", std::ios::binary);
    if (!bfile) return;

    std::vector<size_t> sizes    = program.getInfo<CL_PROGRAM_BINARY_SIZES>();
    std::vector<char*>  binaries = program.getInfo<CL_PROGRAM_BINARIES>();

    assert(sizes.size() == 1);

    bfile.write((char*)&sizes[0], sizeof(size_t));
    bfile.write(binaries[0], sizes[0]);
    delete[] binaries[0];
}
Example #5
0
/// Create and build a program from source string.
inline vex::backend::program build_sources(
        const command_queue &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

    std::string compile_options = options + " " + get_compile_options(queue);

    queue.context().set_current();

    auto cc = queue.device().compute_capability();
    std::ostringstream ccstr;
    ccstr << std::get<0>(cc) << std::get<1>(cc);

    sha1_hasher sha1;
    sha1.process(source)
        .process(queue.device().name())
        .process(compile_options)
        .process(ccstr.str())
        ;

    std::string hash = static_cast<std::string>(sha1);

    // Write source to a .cu file
    std::string basename = program_binaries_path(hash, true) + "kernel";
    std::string ptxfile  = basename + ".ptx";

    if ( !boost::filesystem::exists(ptxfile) ) {
        std::string cufile = basename + ".cu";

        {
            std::ofstream f(cufile);
            f << source;
        }

        // Compile the source to ptx.
        std::ostringstream cmdline;
        cmdline
            << "nvcc -ptx -O3"
            << " -arch=sm_" << std::get<0>(cc) << std::get<1>(cc)
            << " " << compile_options
            << " -o " << ptxfile << " " << cufile;
        if (0 != system(cmdline.str().c_str()) ) {
#ifndef VEXCL_SHOW_KERNELS
            std::cerr << source << std::endl;
#endif

            vex::detail::print_backtrace();
            throw std::runtime_error("nvcc invocation failed");
        }
    }

    // Load the compiled ptx.
    CUmodule prg;
    cuda_check( cuModuleLoad(&prg, ptxfile.c_str()) );

    return program(queue.context(), prg);
}