Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support running OpenCL kernels #251

Open
jerryct opened this issue Sep 19, 2021 · 0 comments
Open

Support running OpenCL kernels #251

jerryct opened this issue Sep 19, 2021 · 0 comments

Comments

@jerryct
Copy link

jerryct commented Sep 19, 2021

The PR #250 should start a discussion about a potential change to run OpenCL kernels. Demo / testing function to compile shaders uses glslangValidator to compile GLSL into SPIR-V. Similar to this https://github.com/google/clspv exists to compile OpenCL kernels into SPIR-V. So the examples from the documentation can be rewritten as

#define VULKAN_HPP_NO_SMART_HANDLE
#include "kompute/Algorithm.hpp"
#include "kompute/Manager.hpp"
#include "kompute/Sequence.hpp"
#include "kompute/Tensor.hpp"
#include "kompute/operations/OpTensorSyncDevice.hpp"
#include "kompute/operations/OpTensorSyncLocal.hpp"
#include <fmt/format.h>
#include <fmt/ostream.h>
#include <fstream>
#include <string>
#include <vector>

std::vector<uint32_t> compileSource(const std::string &source) {
  if (system(std::string("clspv/_build/bin/clspv - -o tmp_kp_opencl.cl.spv << END\n" + source + "\nEND").c_str()))
    throw std::runtime_error("Error running glslangValidator command");
  std::ifstream fileStream("tmp_kp_opencl.cl.spv", std::ios::binary);
  std::vector<char> buffer;
  buffer.insert(buffer.begin(), std::istreambuf_iterator<char>(fileStream), {});
  return {(uint32_t *)buffer.data(), (uint32_t *)(buffer.data() + buffer.size())};
}

int main() {
  std::string shader(R"(
__kernel void foo(__global float* x, float y) {
    x[get_global_id(0)]+=y;
})");

  std::vector<uint32_t> spirv = compileSource(shader);

  kp::Manager mgr(0, {}, {});

  std::vector<std::shared_ptr<kp::Tensor>> tensors{mgr.tensor({23, 0, 0})};

  std::shared_ptr<kp::Algorithm> algo = mgr.algorithm(tensors, spirv, kp::Workgroup({3}), {}, {42.0});

  std::shared_ptr<kp::Sequence> sq = mgr.sequence()
                                         ->record<kp::OpTensorSyncDevice>(tensors)
                                         ->record<kp::OpAlgoDispatch>(algo) //, std::vector<float>{72.0})
                                         ->record<kp::OpAlgoDispatch>(algo)
                                         ->record<kp::OpTensorSyncLocal>(tensors)
                                         ->eval();

  for (float f : tensors[0]->vector<float>()) {
    fmt::print("{}, ", f);
  }
  fmt::print("\n");

  tensors[0]->data<float>()[0] = 23,

  sq->eval();

  for (float f : tensors[0]->vector<float>()) {
    fmt::print("{}, ", f);
  }
  fmt::print("\n");
}

The code above only changed glslangValidator in compileSource to clspv and shader is written in OpenCL C. It prints as expected.

107, 84, 84, 
107, 168, 168,

Currently kcompute hard-codes the entry point to main. The change I had to made to get the above example working was changing main to foo. The reason for this is that OpenCL does not allow a kernel to be named main:

$ cat test.cl 
__kernel void main(__global float* x, float y) {
    x[get_global_id(0)]=y;
}
$ clspv/_build/bin/clspv test.cl
test.cl:1:15: error: kernel cannot be called 'main'
__kernel void main(__global float* x, float y) {
              ^

The question now could we change the default? One idea could be to choose a different hard-coded name, e.g. entry_point. Or more flexible, allow to specify an entry_point here either by adding another parameter or create a small class wrapping the entry point name and the binary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant