From 59411ea4cecd69ec6851b1f04836434d6b46d83b Mon Sep 17 00:00:00 2001 From: Robin van Grinsven Date: Mon, 8 Sep 2025 13:20:35 +0200 Subject: [PATCH] good import. --- .gitignore | 1 + compile_test.cpp | 182 ++++++++++++++++++++++++++++++++++++++++++++ julia/vector_add.jl | 28 ++----- src/main.cpp | 29 +++---- 4 files changed, 204 insertions(+), 36 deletions(-) create mode 100644 compile_test.cpp diff --git a/.gitignore b/.gitignore index b8b31a0..409b204 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /docs/2025 /CMakeCache.txt *.zip +/build/ diff --git a/compile_test.cpp b/compile_test.cpp new file mode 100644 index 0000000..8c406b1 --- /dev/null +++ b/compile_test.cpp @@ -0,0 +1,182 @@ +// opencl_cache.cpp +#include // OpenCL C++ bindings +#include +#include +#include +#include +#include +#include // C++17 +#include + +// ------------------------------------------------------------------- +// Helpers +// ------------------------------------------------------------------- + +// Read a text file into a string +std::string read_file(const std::string &path) +{ + std::ifstream f(path, std::ios::in | std::ios::binary); + if (!f) throw std::runtime_error("Cannot open file: " + path); + std::ostringstream ss; + ss << f.rdbuf(); + return ss.str(); +} + +// Read a binary file into a std::vector +std::vector read_binary(const std::string &path) +{ + std::ifstream f(path, std::ios::binary); + if (!f) throw std::runtime_error("Cannot open binary file: " + path); + return std::vector(std::istreambuf_iterator(f), + std::istreambuf_iterator()); +} + +// Write a binary buffer to file +void write_binary(const std::string &path, const std::vector &data) +{ + std::ofstream f(path, std::ios::binary); + if (!f) throw std::runtime_error("Cannot write binary file: " + path); + f.write(reinterpret_cast(data.data()), data.size()); +} + +// Create a unique key for the device (vendor + name + global mem size) +std::string device_key(const cl::Device &dev) +{ + std::ostringstream ss; + ss << dev.getInfo() + << "-" << dev.getInfo() + << "-" << dev.getInfo(); + return ss.str(); +} + +// ------------------------------------------------------------------- +// Main +// ------------------------------------------------------------------- +int main() +{ + try + { + // 1) Pick the first GPU device on the first platform + std::vector platforms; + cl::Platform::get(&platforms); + if (platforms.empty()) + throw std::runtime_error("No OpenCL platforms found"); + + cl::Platform platform = platforms[0]; + std::vector devices; + platform.getDevices(CL_DEVICE_TYPE_GPU, &devices); + if (devices.empty()) + throw std::runtime_error("No GPU devices on the platform"); + + cl::Device device = devices[0]; + std::cout << "Using platform: " + << platform.getInfo() << '\n'; + std::cout << "Using device : " + << device.getInfo() << '\n'; + + // 2) Context & cache file name + cl::Context ctx(device); + std::string bin_file = device_key(device) + ".bin"; + std::filesystem::path bin_path = std::filesystem::current_path() / bin_file; + + cl::Program program; + + // 3) If we already have a binary, load it + if (std::filesystem::exists(bin_path)) + { + std::cout << "Loading binary from " << bin_path << '\n'; + std::vector bin = read_binary(bin_path.string()); + + // OpenCL expects an array of *unsigned char* pointers, one per + // device. We are using only one device here. + std::vector binaries(1, bin.data()); + std::vector lengths(1, bin.size()); + + std::vector progs(1); + cl_int err = ctx.createProgramWithBinary(devices, + lengths, + binaries.data(), + nullptr, + &progs[0]); + + if (err != CL_SUCCESS) + throw std::runtime_error("clCreateProgramWithBinary failed"); + + program = progs[0]; + } + else + { + // 4) Compile from source, extract the binary, save it + + std::cout << "Compiling source (first run)...\n"; + + std::string src = read_file("example.cl"); + cl::Program::Sources srcs(1, { src.c_str(), src.length() + 1 }); + + program = cl::Program(ctx, srcs); + cl_int err = program.build(devices); + if (err != CL_SUCCESS) + { + std::string log = program.getBuildInfo(device); + throw std::runtime_error("Program build failed: " + log); + } + + // Retrieve the binary + std::vector bin; + std::vector lengths; + program.getInfo(CL_PROGRAM_BINARY_SIZES, &lengths); + program.getInfo(CL_PROGRAM_BINARIES, &bin); + + // Save it for next run + write_binary(bin_path.string(), std::vector(bin.begin(), bin.end())); + std::cout << "Saved binary to " << bin_path << '\n'; + } + + // ------------------------------------------------------------------- + // 5) Demo: add two float vectors + // ------------------------------------------------------------------- + size_t N = 1024; + std::vector a(N, 1.0f), b(N, 2.0f), c(N, 0.0f); + + // Allocate device buffers + cl::Buffer bufA(ctx, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + sizeof(float) * N, a.data()); + cl::Buffer bufB(ctx, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, + sizeof(float) * N, b.data()); + cl::Buffer bufC(ctx, CL_MEM_WRITE_ONLY, + sizeof(float) * N); + + // Create kernel + cl::Kernel kernel(program, "add_vectors"); + + // Set arguments + kernel.setArg(0, bufA); + kernel.setArg(1, bufB); + kernel.setArg(2, bufC); + + // Launch + cl::CommandQueue queue(ctx, device); + queue.enqueueNDRangeKernel(kernel, cl::NullRange, + cl::NDRange(N), cl::NullRange); + queue.finish(); + + // Read back + queue.enqueueReadBuffer(bufC, CL_TRUE, 0, + sizeof(float) * N, c.data()); + + // Verify a few elements + bool ok = true; + for (size_t i = 0; i < N; ++i) + { + if (c[i] != a[i] + b[i]) { ok = false; break; } + } + std::cout << "Demo " << (ok ? "succeeded" : "failed") << '\n'; + } + catch (const std::exception &e) + { + std::cerr << "ERROR: " << e.what() << '\n'; + return 1; + } + + return 0; +} diff --git a/julia/vector_add.jl b/julia/vector_add.jl index a91e3d8..3cc68d6 100644 --- a/julia/vector_add.jl +++ b/julia/vector_add.jl @@ -1,4 +1,5 @@ using OpenCL, pocl_jll +using BenchmarkTools function vadd(a, b, c) gid = get_global_id(1) @@ -6,28 +7,11 @@ function vadd(a, b, c) return end -a = rand(Float32, 50_000) -b = rand(Float32, 50_000) - -d_a = CLArray(a) -d_b = CLArray(b) -d_c = similar(d_a) - -@opencl global_size=size(a) vadd(d_a, d_b, d_c) - -c = Array(d_c) - -@assert a + b ≈ c -using OpenCL, pocl_jll - -function vadd(a, b, c) - gid = get_global_id(1) - @inbounds c[gid] = a[gid] + b[gid] - return -end - -a = rand(Float32, 50_000) -b = rand(Float32, 50_000) +size = 50 + +a = rand(Float32, size) +b = rand(Float32, size) + d_a = CLArray(a) d_b = CLArray(b) diff --git a/src/main.cpp b/src/main.cpp index b436aa1..1ab863f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,7 +3,7 @@ #include // opencl -#include +#include // raylib // #include // sqllite @@ -11,12 +11,25 @@ //#include "include/layers.hpp" +cl::Platform select_platform (){ + + std::vector all_platforms; + cl::Platform::get(&all_platforms); + if(all_platforms.size() == 0) + { + std::cout << "No Platforms found. Check OpenCl installation!\n"; + exit(1); + } + + return all_platforms[0]; +} + int main(){ // import data cl::Platform default_platform=select_platform(); - std::cout << "Using platform: "<()<<"\n"; + std::cout << "Using platform: "<< default_platform.getInfo() <<"\n"; return 0; @@ -29,15 +42,3 @@ int main(){ // opencl sim (every 15 seconds) swap data every 15 seconds } -cl::Platform select_platform (){ - - std::vector all_platforms; - cl::Platform::get(&all_platforms); - if(all_platforms.size() == 0) - { - std::cout << "No Platforms found. Check OpenCl installation!\n"; - exit(1); - } - - return all_platforms[0] -}