diff --git a/examples/linear_regression/CMakeLists.txt b/examples/linear_regression/CMakeLists.txt new file mode 100644 index 000000000..c76764042 --- /dev/null +++ b/examples/linear_regression/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.17.0) +project(kompute_linear_reg VERSION 0.1.0) + +set(CMAKE_CXX_STANDARD 17) + +option(KOMPUTE_OPT_ENABLE_SPDLOG "Extra compile flags for Kompute, see docs for full list" 1) +set(KOMPUTE_EXTRA_CXX_FLAGS "" CACHE STRING "Extra compile flags for Kompute, see docs for full list") + +if(KOMPUTE_OPT_ENABLE_SPDLOG) + set(KOMPUTE_EXTRA_CXX_FLAGS "${KOMPUTE_EXTRA_CXX_FLAGS} -DKOMPUTE_ENABLE_SPDLOG=1") +endif() + +# It is necessary to pass the DEBUG or RELEASE flag accordingly to Kompute +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG=1 ${KOMPUTE_EXTRA_CXX_FLAGS}") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DRELEASE=1 ${KOMPUTE_EXTRA_CXX_FLAGS}") + +find_package(kompute REQUIRED) +find_package(Vulkan REQUIRED) +find_package(spdlog REQUIRED) +find_package(fmt REQUIRED) + +add_executable(kompute_linear_reg + src/Main.cpp) + +target_link_libraries(kompute_linear_reg + kompute::kompute + Vulkan::Vulkan + fmt::fmt + spdlog::spdlog +) + diff --git a/examples/linear_regression/shaders/glsl/logistic_regression.comp b/examples/linear_regression/shaders/glsl/logistic_regression.comp new file mode 100644 index 000000000..9fd76619b --- /dev/null +++ b/examples/linear_regression/shaders/glsl/logistic_regression.comp @@ -0,0 +1,56 @@ +#version 450 + +layout (constant_id = 0) const uint M = 0; + +layout (local_size_x = 1) in; + +layout(set = 0, binding = 0) buffer bxi { float xi[]; }; +layout(set = 0, binding = 1) buffer bxj { float xj[]; }; +layout(set = 0, binding = 2) buffer by { float y[]; }; +layout(set = 0, binding = 3) buffer bwin { float win[]; }; +layout(set = 0, binding = 4) buffer bwouti { float wouti[]; }; +layout(set = 0, binding = 5) buffer bwoutj { float woutj[]; }; +layout(set = 0, binding = 6) buffer bbin { float bin[]; }; +layout(set = 0, binding = 7) buffer bbout { float bout[]; }; +layout(set = 0, binding = 8) buffer blout { float lout[]; }; + +float m = float(M); + +float sigmoid(float z) { + return 1.0 / (1.0 + exp(-z)); +} + +float inference(vec2 x, vec2 w, float b) { + // Compute the linear mapping function + float z = dot(w, x) + b; + // Calculate the y-hat with sigmoid + float yHat = sigmoid(z); + return yHat; +} + +float calculateLoss(float yHat, float y) { + return -(y * log(yHat) + (1.0 - y) * log(1.0 - yHat)); +} + +void main() { + uint idx = gl_GlobalInvocationID.x; + + vec2 wCurr = vec2(win[0], win[1]); + float bCurr = bin[0]; + + vec2 xCurr = vec2(xi[idx], xj[idx]); + float yCurr = y[idx]; + + float yHat = inference(xCurr, wCurr, bCurr); + + float dZ = yHat - yCurr; + vec2 dW = (1. / m) * xCurr * dZ; + float dB = (1. / m) * dZ; + wouti[idx] = dW.x; + woutj[idx] = dW.y; + bout[idx] = dB; + + lout[idx] = calculateLoss(yHat, yCurr); +} + + diff --git a/examples/linear_regression/src/Main.cpp b/examples/linear_regression/src/Main.cpp new file mode 100755 index 000000000..6198b17b7 --- /dev/null +++ b/examples/linear_regression/src/Main.cpp @@ -0,0 +1,77 @@ + +#include +#include +#include + +#include "kompute/Kompute.hpp" + +int main() +{ +#if KOMPUTE_ENABLE_SPDLOG + spdlog::set_level( + static_cast(SPDLOG_ACTIVE_LEVEL)); +#endif + + uint32_t ITERATIONS = 100; + float learningRate = 0.1; + + std::shared_ptr xI{ new kp::Tensor({ 0, 1, 1, 1, 1 }) }; + std::shared_ptr xJ{ new kp::Tensor({ 0, 0, 0, 1, 1 }) }; + + std::shared_ptr y{ new kp::Tensor({ 0, 0, 0, 1, 1 }) }; + + std::shared_ptr wIn{ new kp::Tensor({ 0.001, 0.001 }) }; + std::shared_ptr wOutI{ new kp::Tensor({ 0, 0, 0, 0, 0 }) }; + std::shared_ptr wOutJ{ new kp::Tensor({ 0, 0, 0, 0, 0 }) }; + + std::shared_ptr bIn{ new kp::Tensor({ 0 }) }; + std::shared_ptr bOut{ new kp::Tensor({ 0, 0, 0, 0, 0 }) }; + + std::shared_ptr lOut{ new kp::Tensor({ 0, 0, 0, 0, 0 }) }; + + std::vector> params = { xI, xJ, y, + wIn, wOutI, wOutJ, + bIn, bOut, lOut }; + + kp::Manager mgr; + + std::weak_ptr sqWeakPtr = mgr.getOrCreateManagedSequence("createTensors"); + std::shared_ptr sq = sqWeakPtr.lock(); + + sq->begin(); + + sq->record(params); + + sq->end(); + sq->eval(); + + // Record op algo base + sq->begin(); + + sq->record({ wIn, bIn }); + + sq->record>( + params, "shaders/glsl/logistic_regression.comp"); + + sq->record({ wOutI, wOutJ, bOut, lOut }); + + sq->end(); + + // Iterate across all expected iterations + for (size_t i = 0; i < ITERATIONS; i++) { + + sq->eval(); + + for (size_t j = 0; j < bOut->size(); j++) { + wIn->data()[0] -= learningRate * wOutI->data()[j]; + wIn->data()[1] -= learningRate * wOutJ->data()[j]; + bIn->data()[0] -= learningRate * bOut->data()[j]; + } + } + + std::cout << "RESULTS" << std::endl; + std::cout << "w1: " << wIn->data()[0] << std::endl; + std::cout << "w2: " << wIn->data()[1] << std::endl; + std::cout << "b: " << bIn->data()[0] << std::endl; +} +