Skip to content

Commit

Permalink
gh-174: impl cl shared compiled program cache
Browse files Browse the repository at this point in the history
  • Loading branch information
EgorOrachyov committed Dec 2, 2022
1 parent df92bff commit e564ed3
Show file tree
Hide file tree
Showing 20 changed files with 491 additions and 104 deletions.
8 changes: 6 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,12 @@ if (SPLA_BUILD_OPENCL)
src/opencl/cl_accelerator.hpp
src/opencl/cl_algo_registry.cpp
src/opencl/cl_algo_registry.hpp
src/opencl/cl_kernel_builder.cpp
src/opencl/cl_kernel_builder.hpp
src/opencl/cl_program.cpp
src/opencl/cl_program.hpp
src/opencl/cl_program_builder.cpp
src/opencl/cl_program_builder.hpp
src/opencl/cl_program_cache.cpp
src/opencl/cl_program_cache.hpp
src/opencl/cl_dense_vec.hpp
src/opencl/cl_coo_vec.hpp
src/opencl/cl_csr.hpp
Expand Down
1 change: 1 addition & 0 deletions include/spla/timer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ namespace spla {
SPLA_API void lap_end();
SPLA_API void print(std::ostream& out = std::cout) const;
[[nodiscard]] SPLA_API double get_elapsed_ms() const;
[[nodiscard]] SPLA_API double get_elapsed_sec() const;
[[nodiscard]] SPLA_API double get_elapsed_lap_ms() const;
[[nodiscard]] SPLA_API const std::vector<double>& get_laps_ms() const;

Expand Down
7 changes: 7 additions & 0 deletions src/opencl/cl_accelerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,13 @@

#include "cl_accelerator.hpp"

#include <opencl/cl_program_cache.hpp>

namespace spla {

CLAccelerator::CLAccelerator() = default;
CLAccelerator::~CLAccelerator() = default;

Status CLAccelerator::init() {
if (set_platform(0) != Status::Ok)
return Status::PlatformNotFound;
Expand All @@ -41,6 +46,8 @@ namespace spla {

build_description();

m_cache = std::make_unique<CLProgramCache>();

// Output handy info
LOG_MSG(Status::Ok, "Initialize accelerator: " << get_description());

Expand Down
11 changes: 7 additions & 4 deletions src/opencl/cl_accelerator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ namespace spla {
*/
class CLAccelerator final : public Accelerator {
public:
~CLAccelerator() override = default;
CLAccelerator();
~CLAccelerator() override;

Status init() override;
Status set_platform(int index) override;
Expand All @@ -75,6 +76,7 @@ namespace spla {
cl::Context& get_context() { return m_context; }
cl::CommandQueue& get_queue_default() { return m_queues.front(); }
std::vector<cl::CommandQueue>& get_queues() { return m_queues; }
class CLProgramCache* get_cache() { return m_cache.get(); }

[[nodiscard]] const std::string& get_vendor_name() const { return m_vendor_name; }
[[nodiscard]] const std::string& get_vendor_code() const { return m_vendor_code; }
Expand All @@ -88,9 +90,10 @@ namespace spla {
private:
void build_description();

cl::Platform m_platform;
cl::Device m_device;
cl::Context m_context;
cl::Platform m_platform;
cl::Device m_device;
cl::Context m_context;
std::unique_ptr<class CLProgramCache> m_cache;

std::string m_name = "OpenCL";
std::string m_description;
Expand Down
35 changes: 18 additions & 17 deletions src/opencl/cl_mxv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
#include <core/tvector.hpp>

#include <opencl/cl_formats.hpp>
#include <opencl/cl_kernel_builder.hpp>
#include <opencl/cl_program_builder.hpp>
#include <opencl/generated/auto_mxv.hpp>

#include <algorithm>
Expand Down Expand Up @@ -255,8 +255,9 @@ namespace spla {
assert(m_block_count >= 1);
assert(m_block_size * m_block_count == get_acc_cl()->get_wave_size());

CLKernelBuilder kernel_builder;
kernel_builder
CLProgramBuilder program_builder;
program_builder
.set_key("mxv")
.add_define("WARP_SIZE", get_acc_cl()->get_wave_size())
.add_define("BLOCK_SIZE", m_block_size)
.add_define("BLOCK_COUNT", m_block_count)
Expand All @@ -266,26 +267,26 @@ namespace spla {
.add_op("OP_SELECT", op_select.template as<OpSelect>())
.add_code(source_mxv);

if (!kernel_builder.build()) return false;
if (!program_builder.build()) return false;

m_program = kernel_builder.get_program();
m_kernel_vector = cl::Kernel(m_program, "mxv_vector");
m_kernel_scalar = cl::Kernel(m_program, "mxv_scalar");
m_kernel_config = cl::Kernel(m_program, "mxv_config");
m_kernel_config_scalar = cl::Kernel(m_program, "mxv_config_scalar");
m_program = program_builder.get_program();
m_kernel_vector = m_program->make_kernel("mxv_vector");
m_kernel_scalar = m_program->make_kernel("mxv_scalar");
m_kernel_config = m_program->make_kernel("mxv_config");
m_kernel_config_scalar = m_program->make_kernel("mxv_config_scalar");
m_compiled = true;

return true;
}

cl::Kernel m_kernel_vector;
cl::Kernel m_kernel_scalar;
cl::Kernel m_kernel_config;
cl::Kernel m_kernel_config_scalar;
cl::Program m_program;
uint m_block_size = 0;
uint m_block_count = 0;
bool m_compiled = false;
std::shared_ptr<CLProgram> m_program;
cl::Kernel m_kernel_vector;
cl::Kernel m_kernel_scalar;
cl::Kernel m_kernel_config;
cl::Kernel m_kernel_config_scalar;
uint m_block_size = 0;
uint m_block_count = 0;
bool m_compiled = false;
};

}// namespace spla
Expand Down
36 changes: 36 additions & 0 deletions src/opencl/cl_program.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**********************************************************************************/
/* This file is part of spla project */
/* https://github.com/JetBrains-Research/spla */
/**********************************************************************************/
/* MIT License */
/* */
/* Copyright (c) 2021 JetBrains-Research */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining a copy */
/* of this software and associated documentation files (the "Software"), to deal */
/* in the Software without restriction, including without limitation the rights */
/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */
/* copies of the Software, and to permit persons to whom the Software is */
/* furnished to do so, subject to the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be included in all */
/* copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */
/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */
/* SOFTWARE. */
/**********************************************************************************/

#include "cl_program.hpp"

namespace spla {

cl::Kernel CLProgram::make_kernel(const char* name) {
return cl::Kernel(m_program, name);
}

}// namespace spla
34 changes: 16 additions & 18 deletions src/opencl/cl_kernel_builder.hpp → src/opencl/cl_program.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,11 @@
/* SOFTWARE. */
/**********************************************************************************/

#ifndef SPLA_CL_KERNEL_BUILDER_HPP
#define SPLA_CL_KERNEL_BUILDER_HPP
#ifndef SPLA_CL_PROGRAM_HPP
#define SPLA_CL_PROGRAM_HPP

#include <core/top.hpp>
#include <core/ttype.hpp>
#include <opencl/cl_accelerator.hpp>

#include <sstream>
#include <string>
#include <vector>

Expand All @@ -44,27 +41,28 @@ namespace spla {
*/

/**
* @class CLKernelBuilder
* @brief Runtime opencl program builder
* @class CLProgram
* @brief Compiled opencl program from library sources
*/
class CLKernelBuilder final {
class CLProgram {
public:
CLKernelBuilder& add_define(const char* define, int value);
CLKernelBuilder& add_type(const char* alias, const ref_ptr<Type>& type);
CLKernelBuilder& add_op(const char* name, const ref_ptr<OpBinary>& op);
CLKernelBuilder& add_op(const char* name, const ref_ptr<OpSelect>& op);
CLKernelBuilder& add_code(const char* source);
cl::Kernel make_kernel(const char* name);

bool build();

const std::string& get_source() { return m_source; };
const cl::Program& get_program() { return m_program; };
[[nodiscard]] const std::vector<std::string>& get_defines() const { return m_defines; }
[[nodiscard]] const std::vector<std::string>& get_functions() const { return m_functions; }
[[nodiscard]] const std::vector<std::string>& get_sources() const { return m_sources; }
[[nodiscard]] const std::string& get_source() const { return m_source; }
[[nodiscard]] const std::string& get_key() const { return m_key; }
[[nodiscard]] const cl::Program& get_program() const { return m_program; }

private:
friend class CLProgramBuilder;

std::vector<std::string> m_defines;
std::vector<std::string> m_functions;
std::vector<std::string> m_sources;
std::string m_source;
std::string m_key;
cl::Program m_program;
};

Expand All @@ -74,4 +72,4 @@ namespace spla {

}// namespace spla

#endif//SPLA_CL_KERNEL_BUILDER_HPP
#endif//SPLA_CL_PROGRAM_HPP
Original file line number Diff line number Diff line change
Expand Up @@ -25,33 +25,40 @@
/* SOFTWARE. */
/**********************************************************************************/

#include "cl_kernel_builder.hpp"
#include "cl_program_builder.hpp"

#include <spla/timer.hpp>

namespace spla {

CLKernelBuilder& CLKernelBuilder::add_define(const char* define, int value) {
CLProgramBuilder& CLProgramBuilder::set_key(const char* key) {
m_key = key;
return *this;
}
CLProgramBuilder& CLProgramBuilder::add_define(const char* define, int value) {
m_defines.emplace_back(define + std::string(" ") + std::to_string(value));
return *this;
}
CLKernelBuilder& CLKernelBuilder::add_type(const char* define, const ref_ptr<Type>& type) {
CLProgramBuilder& CLProgramBuilder::add_type(const char* define, const ref_ptr<Type>& type) {
m_defines.emplace_back(define + std::string(" ") + type->get_cpp());
return *this;
}
CLKernelBuilder& CLKernelBuilder::add_op(const char* name, const ref_ptr<OpBinary>& op) {
CLProgramBuilder& CLProgramBuilder::add_op(const char* name, const ref_ptr<OpBinary>& op) {
m_functions.emplace_back(op->get_type_res()->get_cpp() + " " + name + " " + op->get_source());
return *this;
}
CLKernelBuilder& CLKernelBuilder::add_op(const char* name, const ref_ptr<OpSelect>& op) {
CLProgramBuilder& CLProgramBuilder::add_op(const char* name, const ref_ptr<OpSelect>& op) {
m_functions.emplace_back(std::string("bool ") + name + " " + op->get_source());
return *this;
}
CLKernelBuilder& CLKernelBuilder::add_code(const char* source) {
CLProgramBuilder& CLProgramBuilder::add_code(const char* source) {
m_sources.emplace_back(source);
return *this;
}
bool CLKernelBuilder::build() {
bool CLProgramBuilder::build() {
std::stringstream builder;
CLAccelerator* acc = get_acc_cl();
CLAccelerator* acc = get_acc_cl();
CLProgramCache* cache = acc->get_cache();

for (const auto& define : m_defines) {
builder << "#define " << define << "\n";
Expand All @@ -64,14 +71,36 @@ namespace spla {
}

m_source = builder.str();
m_program = cl::Program(acc->get_context(), m_source);
m_program = cache->get_program(m_source);

if (m_program) {
LOG_MSG(Status::Ok, "found program '" << m_key << "' in cache");
return true;
}

if (m_program.build("-cl-std=CL1.2") != CL_SUCCESS) {
LOG_MSG(Status::Error, "failed to build program: " << m_program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(acc->get_device()));
m_program = std::make_shared<CLProgram>();
m_program->m_program = cl::Program(acc->get_context(), m_source);

Timer t;
t.start();
auto status = m_program->m_program.build("-cl-std=CL1.2");
t.stop();

if (status != CL_SUCCESS) {
LOG_MSG(Status::Error, "failed to build program: " << m_program->m_program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(acc->get_device()));
LOG_MSG(Status::Error, "src\n" << m_source);
return false;
}

m_program->m_defines = std::move(m_defines);
m_program->m_functions = std::move(m_functions);
m_program->m_sources = std::move(m_sources);
m_program->m_source = std::move(m_source);
m_program->m_key = std::move(m_key);
LOG_MSG(Status::Ok, "build program '" << m_program->m_key << "' in " << t.get_elapsed_sec() << "sec");

cache->add_program(m_program);

return true;
}

Expand Down
Loading

0 comments on commit e564ed3

Please sign in to comment.