commit f94c6dc47034b433a9d7d44accaf3c280fb0c67c Author: Alessandro Mauri Date: Wed Dec 6 11:23:01 2023 +0100 bruh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ + diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..75869d0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "kompute"] + path = kompute + url = https://github.com/KomputeProject/kompute/ diff --git a/kompute b/kompute new file mode 160000 index 0000000..1d449da --- /dev/null +++ b/kompute @@ -0,0 +1 @@ +Subproject commit 1d449daa11257442de6c6c9ffa48a587c3c92a68 diff --git a/test1/.gitignore b/test1/.gitignore new file mode 100644 index 0000000..e37dbbe --- /dev/null +++ b/test1/.gitignore @@ -0,0 +1,3 @@ +*.spv +*.comp +test1 diff --git a/test1/Makefile b/test1/Makefile new file mode 100644 index 0000000..4aa7d61 --- /dev/null +++ b/test1/Makefile @@ -0,0 +1,9 @@ +CPPFLAGS = -Wall -Wextra -g +# link kompute as a static library and the rest as dynamic +LDFLAGS = -L/usr/local/lib -Wl,-Bstatic -lkompute -lkp_logger -Wl,-Bdynamic -lvulkan -lfmt -Wl,--as-needed + +test1: main.cpp + g++ ${CPPFLAGS} main.cpp -o test1 ${LDFLAGS} + +clean: + rm -f test1 diff --git a/test1/README b/test1/README new file mode 100644 index 0000000..8bd3604 --- /dev/null +++ b/test1/README @@ -0,0 +1,2 @@ +test1: +simple sum, sum of two tensors diff --git a/test1/main.cpp b/test1/main.cpp new file mode 100644 index 0000000..da2506a --- /dev/null +++ b/test1/main.cpp @@ -0,0 +1,70 @@ +#include +#include +#include + +#include + + +const std::string shader_code(R"(#version 450 +// The execution structure +layout (local_size_x = 1) in; + +// The buffers are provided via the tensors +layout(binding = 0) buffer bufA { float a[]; }; +layout(binding = 1) buffer bufB { float b[]; }; +layout(binding = 2) buffer bufOut { float o[]; }; + +void main() { + uint index = gl_GlobalInvocationID.x; + o[index] = a[index] * b[index]; +})"); + + +static std::vector compileSource(const std::string& source) +{ + std::ofstream fileOut("tmp_kp_shader.comp"); + fileOut << source; + fileOut.close(); + if (system(std::string("glslangValidator -V tmp_kp_shader.comp -o tmp_kp_shader.comp.spv").c_str())) + throw std::runtime_error("Error running glslangValidator command"); + std::ifstream fileStream("tmp_kp_shader.comp.spv", std::ios::binary); + std::vector buffer; + buffer.insert(buffer.begin(), std::istreambuf_iterator(fileStream), {}); + return {(uint32_t*)buffer.data(), (uint32_t*)(buffer.data() + buffer.size())}; +} + + +int main() +{ + kp::Manager mgr; + + std::shared_ptr> tensorInA = mgr.tensor({ 2.0, 4.0, 6.0 }); + std::shared_ptr> tensorInB = mgr.tensor({ 0.0, 1.0, 2.0 }); + std::shared_ptr> tensorOut = mgr.tensor({ 0.0, 0.0, 0.0 }); + + const std::vector> params = { + tensorInA, tensorInB, tensorOut + }; + + const std::vector shader = compileSource(shader_code); + std::shared_ptr algo = mgr.algorithm(params, shader); + + mgr.sequence() + ->record(params) + ->record(algo) + ->record(params) + ->eval(); + + // prints "Output { 0 4 12 }" + std::cout << "Output: { "; + for (const float& elem : tensorOut->vector()) { + std::cout << elem << " "; + } + std::cout << "}" << std::endl; + + if (tensorOut->vector() != std::vector{ 0, 4, 12 }) { + throw std::runtime_error("Result does not match"); + } + + return 0; +} diff --git a/test2/.gitignore b/test2/.gitignore new file mode 100644 index 0000000..e37dbbe --- /dev/null +++ b/test2/.gitignore @@ -0,0 +1,3 @@ +*.spv +*.comp +test1 diff --git a/test2/Makefile b/test2/Makefile new file mode 100644 index 0000000..8e8b2ea --- /dev/null +++ b/test2/Makefile @@ -0,0 +1,9 @@ +CPPFLAGS = -Wall -Wextra -g +# link kompute as a static library and the rest as dynamic +LDFLAGS = -L/usr/local/lib -Wl,-Bstatic -lkompute -lkp_logger -Wl,-Bdynamic -lvulkan -lfmt -Wl,--as-needed + +test2: main.cpp + g++ ${CPPFLAGS} main.cpp -o test2 ${LDFLAGS} + +clean: + rm -f test2 diff --git a/test2/README b/test2/README new file mode 100644 index 0000000..a54533c --- /dev/null +++ b/test2/README @@ -0,0 +1,2 @@ +test2: +matrix multiplication diff --git a/test2/main.cpp b/test2/main.cpp new file mode 100644 index 0000000..274a3db --- /dev/null +++ b/test2/main.cpp @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +static std::vector compile_shader(const std::string& source) +{ + std::ofstream fileOut("tmp_kp_shader.comp"); + fileOut << source; + fileOut.close(); + if (system(std::string("glslangValidator -V tmp_kp_shader.comp -o tmp_kp_shader.comp.spv").c_str())) + throw std::runtime_error("Error running glslangValidator command"); + std::ifstream fileStream("tmp_kp_shader.comp.spv", std::ios::binary); + std::vector buffer; + buffer.insert(buffer.begin(), std::istreambuf_iterator(fileStream), {}); + return {(uint32_t*)buffer.data(), (uint32_t*)(buffer.data() + buffer.size())}; +} + + + +static std::string shader_to_string(const char *path) +{ + std::ifstream comp_file; + + comp_file.open(path); + if (comp_file.is_open() == false) { + return std::string("// bad code"); + } + + std::ostringstream outstr; + outstr << comp_file.rdbuf(); + return outstr.str(); +} + + +// the sed replace command as a function +// 1. /pattern/replace/ +// 2. /pattern// +static std::string regex_replace(const char *expr_string, std::string str) +{ + std::string expr(expr_string); + std::string pattern, replace; + + if (expr.size() < 3 || expr[0] != '/' || expr.back() != '/') { + return str; + } else { + // shift 1 + expr = expr.substr(1, expr.size()-2); + } + for (size_t pos = 0, nxpos = 0; ; pos = nxpos) { + nxpos = expr.find("/", pos); + if (nxpos == std::string::npos) { + break; + } + // skip escaped '/' + if (nxpos > 0 && expr[nxpos-1] == '\\') { + if (nxpos > 1 && expr[nxpos-2] != '\\') { + continue; + } + } + pattern = expr.substr(0, nxpos); + replace = expr.substr(nxpos+1); + break; + } + if (pattern.empty()) { + return str; + } + + std::regex reg(pattern); + std::string newstr = std::regex_replace(str, reg, replace); + return newstr; +} + + +template std::string regex_subst(const char *expr, T val, std::string str) +{ + std::regex reg(expr); + std::regex_match(); + return newstr; +} + + +int main() +{ + // create the kompute manager + kp::Manager mgr; + + // C = A*B + float matrixA[1024][1024] = {0}; + float matrixB[1024][1024] = {0}; + float matrixC[1024][1024] = {0}; + // fill an identity matrix + for (int y = 0; y < 1024; y++) { + matrixA[y][y] = 1.0; + } + // fill a matrix with data + for (int y = 0; y < 1024; y++) { + for (int x = 0; x < 1024; x++) { + matrixB[y][x] = x*0.74 - y*0.22; + } + } + + // create the tensors, tensors are just arrays, in the shader we will have + // to describe how it translates to matrices + kp::Tensor::TensorDataTypes dtype = kp::Tensor::TensorDataTypes::eFloat; + + // auto because fuck C++ + auto tensorA = mgr.tensor(matrixA, 1024*1024, sizeof(float), dtype); + auto tensorB = mgr.tensor(matrixB, 1024*1024, sizeof(float), dtype); + auto tensorC = mgr.tensor(matrixC, 1024*1024, sizeof(float), dtype); + + const std::vector> params = { + tensorA, tensorB, tensorC + }; + + // workgroup, dispatch a 2D array of workgroups (2D matrices) + // TODO: determine the size of the workgroups by doing some calls to vk + const int wgrp_x = 32, wgrp_y = 32; + // this should call vkCmdDispatch(x, y, z) + kp::Workgroup workgroup({wgrp_x, wgrp_y, 1}); + + // substitute the values in the shader + const char *shader_path = "shader.comp"; + std::string shader_str = shader_to_string(shader_path); + shader_str = regex_replace("/{lcsize_x}/", shader_str); + const std::vector shader = compile_shader(shader_to_string("shader.comp")); + + + std::shared_ptr algo = mgr.algorithm( + params, + shader, + workgroup, + {1024.0} + ); + + mgr.sequence() + ->record(params) + ->record(algo) + ->record(params) + ->eval(); + + + // print the resulting matrix + std::cout << "Output: { "; + for (const float& elem : tensorC->vector()) { + printf("%.2f, ", elem); + } + std::cout << "}" << std::endl; + + return 0; +} diff --git a/test2/test2 b/test2/test2 new file mode 100755 index 0000000..401d056 Binary files /dev/null and b/test2/test2 differ