Updated the array_multiplication example

Signed-off-by: Fabian Sauter <sauter.fabian@mailbox.org>
This commit is contained in:
Fabian Sauter 2022-06-24 09:56:37 +02:00
parent 6fac581fa9
commit 7d16b73d14
7 changed files with 130 additions and 137 deletions

View file

@ -1,40 +1,37 @@
cmake_minimum_required(VERSION 3.4.1)
project(kompute_array_mult VERSION 0.1.0)
cmake_minimum_required(VERSION 3.15)
project(kompute_array_mult)
set(CMAKE_CXX_STANDARD 14)
option(KOMPUTE_ARR_OPT_INSTALLED_KOMPUTE "Enable if you prefer to use your installed Kompute library" 0)
option(KOMPUTE_OPT_ENABLE_SPDLOG "Extra compile flags for Kompute, see docs for full list" 0)
set(KOMPUTE_EXTRA_CXX_FLAGS "" CACHE STRING "Extra compile flags for Kompute, see docs for full list")
# Set a default build type if none was specified
# Based on: https://github.com/openchemistry/tomviz/blob/master/cmake/BuildType.cmake
set(DEFAULT_BUILD_TYPE "Release")
if(KOMPUTE_OPT_ENABLE_SPDLOG)
set(KOMPUTE_EXTRA_CXX_FLAGS "${KOMPUTE_EXTRA_CXX_FLAGS} -DKOMPUTE_ENABLE_SPDLOG=1")
if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
set(DEFAULT_BUILD_TYPE "Debug")
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}")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to '${DEFAULT_BUILD_TYPE}' as none was specified.")
set(CMAKE_BUILD_TYPE "${DEFAULT_BUILD_TYPE}" CACHE STRING "Choose the type of build." FORCE)
if(KOMPUTE_ARR_OPT_INSTALLED_KOMPUTE)
find_package(kompute REQUIRED)
else()
add_subdirectory(../../ ${CMAKE_CURRENT_BINARY_DIR}/kompute_build)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
find_package(Vulkan REQUIRED)
add_executable(kompute_array_mult
src/Main.cpp)
target_link_libraries(kompute_array_mult
kompute::kompute
Vulkan::Vulkan)
include_directories(
../../single_include/)
if(KOMPUTE_OPT_ENABLE_SPDLOG)
target_link_libraries(kompute_array_mult
spdlog::spdlog)
if(WIN32) # Install dlls in the same directory as the executable on Windows
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
endif()
include(FetchContent)
FetchContent_Declare(kompute GIT_REPOSITORY https://github.com/COM8/kompute.git
GIT_TAG 01a0485f461e3d080b277aeb43c06a3ede8bd75d) # The commit hash for a dev version before v0.9.0. Replace with the latest from: https://github.com/KomputeProject/kompute/releases
FetchContent_MakeAvailable(kompute)
include_directories(${kompute_SOURCE_DIR}/src/include)
# Add to the list, so CMake can later find the code to compile shaders to header files
list(APPEND CMAKE_PREFIX_PATH "${kompute_SOURCE_DIR}/cmake")
add_subdirectory(shader)
add_subdirectory(src)

View file

@ -1,30 +1,39 @@
# Kompute Array Multiplication Example
This folder contains an end to end Kompute Example that implements logistic regression.
This example is structured such that you will be able to extend it for your project.
It contains a cmake build configuration that can be used in your production applications.
It contains a CMake build configuration that can be used in your production applications.
## Building the example
You will notice that it's a standalone project, so you can re-use it for your application.
It uses CMake's [`fetch_content`](https://cmake.org/cmake/help/latest/module/FetchContent.html) to consume Kompute as a dependency.
To build you just need to run the CMake command in this folder as follows:
This project has the option to either import the Kompute dependency relative to the project or use your existing installation of Kompute.
To build you just need to run the cmake command in this folder as follows:
```
cmake -Bbuild/ \
-DCMAKE_BUILD_TYPE=Debug \
-DKOMPUTE_OPT_INSTALL=0 \
-DKOMPUTE_OPT_ENABLE_SPDLOG=1
```bash
git clone https://github.com/KomputeProject/kompute.git
cd kompute/examples/array_multiplication
mkdir build
cd build
cmake ..
cmake --build .
```
You can pass the following optional parameters based on your desired configuration:
* If you wish to install with spdlog support you just have to pass `-DKOMPUTE_OPT_ENABLE_SPDLOG=1`.
* If you are using a package manager such as `vcpkg` make sure you pass the `-DCMAKE_TOOLCHAIN_FILE=` parameter
* If you wish to load shader from raw glsl string instead of spirv bytes you can use `-DKOMPUTE_ANDROID_SHADER_FROM_STRING`
## Executing
Form inside the `build/` directory run:
### Linux
```bash
./kompute_array_mult
```
### Windows
```bash
.\Debug\kompute_array_mult.exe
```
## Pre-requisites
@ -32,18 +41,5 @@ In order to run this example, you will need the following dependencies:
* REQUIRED
+ The Vulkan SDK must be installed
* OPTIONAL
+ Kompute library must be accessible (by default it uses the source directory)
+ SPDLOG - for logging
+ FMT - for text formatting
We will cover how you can install Kompute in the next section.
For the Vulkan SDK, the simplest way to install it is through [their website](https://vulkan.lunarg.com/sdk/home). You just have to follow the instructions for the relevant platform.
For the other libraries, because they are optional you can just make sure you build and install Kompute with these disabled (this will be covered in more detail below).
Alternatively you can use package managers such as vcpkg to help you install them, although to simplify things you can start without the dependencies first.

View file

@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.15)
# To add more shaders simply copy the vulkan_compile_shader command and replace it with your new shader
vulkan_compile_shader(INFILE my_shader.comp
OUTFILE my_shader.hpp
NAMESPACE "shader"
RELATIVE_PATH "${kompute_SOURCE_DIR}/cmake")
# vulkan_compile_shader(INFILE my_shader2.comp
# OUTFILE my_shader2.hpp
# NAMESPACE "shader"
# RELATIVE_PATH "${kompute_SOURCE_DIR}/cmake")
# Then add it to the library, so you can access it later in your code
add_library(shader "${CMAKE_CURRENT_BINARY_DIR}/my_shader.hpp"
# "${CMAKE_CURRENT_BINARY_DIR}/my_shader2.hpp"
)
set_target_properties(shader PROPERTIES LINKER_LANGUAGE CXX)
target_include_directories(shader PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)

View file

@ -0,0 +1,14 @@
#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];
}

View file

@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 3.15)
add_executable(kompute_array_mult main.cpp)
target_link_libraries(kompute_array_mult PRIVATE shader kompute::kompute)

View file

@ -1,79 +0,0 @@
#include <iostream>
#include <memory>
#include <vector>
#include "kompute/Kompute.hpp"
static std::vector<uint32_t>
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<char> buffer;
buffer.insert(
buffer.begin(), std::istreambuf_iterator<char>(fileStream), {});
return { (uint32_t*)buffer.data(),
(uint32_t*)(buffer.data() + buffer.size()) };
}
int
main()
{
#if KOMPUTE_ENABLE_SPDLOG
spdlog::set_level(
static_cast<spdlog::level::level_enum>(SPDLOG_ACTIVE_LEVEL));
#endif
kp::Manager mgr;
auto tensorInA = mgr.tensor({ 2.0, 4.0, 6.0 });
auto tensorInB = mgr.tensor({ 0.0, 1.0, 2.0 });
auto tensorOut = mgr.tensor({ 0.0, 0.0, 0.0 });
std::string shader(R"(
// The version to use
#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];
}
)");
std::vector<std::shared_ptr<kp::Tensor>> params = { tensorInA,
tensorInB,
tensorOut };
std::shared_ptr<kp::Algorithm> algo =
mgr.algorithm(params, compileSource(shader));
mgr.sequence()
->record<kp::OpTensorSyncDevice>(params)
->record<kp::OpAlgoDispatch>(algo)
->record<kp::OpTensorSyncLocal>(params)
->eval();
// prints "Output { 0 4 12 }"
std::cout << "Output: { ";
for (const float& elem : tensorOut->vector()) {
std::cout << elem << " ";
}
std::cout << "}" << std::endl;
}

View file

@ -0,0 +1,41 @@
#include <iostream>
#include <memory>
#include <vector>
#include "my_shader.hpp"
#include <kompute/Kompute.hpp>
int
main()
{
kp::Manager mgr;
std::shared_ptr<kp::TensorT<float>> tensorInA =
mgr.tensor({ 2.0, 4.0, 6.0 });
std::shared_ptr<kp::TensorT<float>> tensorInB =
mgr.tensor({ 0.0, 1.0, 2.0 });
std::shared_ptr<kp::TensorT<float>> tensorOut =
mgr.tensor({ 0.0, 0.0, 0.0 });
const std::vector<std::shared_ptr<kp::Tensor>> params = { tensorInA,
tensorInB,
tensorOut };
const std::vector<uint32_t> shader = std::vector<uint32_t>(
shader::MY_SHADER_COMP_SPV.begin(), shader::MY_SHADER_COMP_SPV.end());
std::shared_ptr<kp::Algorithm> algo = mgr.algorithm(params, shader);
mgr.sequence()
->record<kp::OpTensorSyncDevice>(params)
->record<kp::OpAlgoDispatch>(algo)
->record<kp::OpTensorSyncLocal>(params)
->eval();
// prints "Output { 0 4 12 }"
std::cout << "Output: { ";
for (const float& elem : tensorOut->vector()) {
std::cout << elem << " ";
}
std::cout << "}" << std::endl;
}