Vulkan Kompute

Principles

  • Single header easy to import library to boost your Vulkan compute experience (WIP)
  • Non-vulkan naming convention to disambiguate Vulkan vs Kompute components
  • Extends the existing vulkan API with a simpler compute-specific interface
  • BYOV: Play nice with existing Vulkan applications with a bring-your-own-Vulkan design
  • TODO

Getting Started

Run your tensors against default or custom equations via the Manager.

int main() {

    kp::Manager mgr; // Automatically selects Device 0

    std::shared_ptr<kp::Tensor> tensorLHS{ new kp::Tensor({ 0.0, 1.0, 2.0 }) };
    mgr.evalOp<kp::OpCreateTensor>({ tensorLHS });

    std::shared_ptr<kp::Tensor> tensorRHS{ new kp::Tensor( { 2.0, 4.0, 6.0 }) };
    mgr.evalOp<kp::OpCreateTensor>({ tensorRHS });

    // TODO: Add capabilities for just output tensor types
    std::shared_ptr<kp::Tensor> tensorOutput{ new kp::Tensor({ 0.0, 0.0, 0.0 }) };
    mgr.evalOp<kp::OpCreateTensor>({ tensorOutput });

    mgr.evalOp<kp::OpMult>({ tensorLHS, tensorRHS, tensorOutput });

    std::cout << fmt::format("Output: {}", tensorOutput.data()) << std::endl;
}

Record commands in a single submit by using a Sequence.

int main() {
    kp::Manager mgr;

    std::shared_ptr<kp::Tensor> tensorLHS{ new kp::Tensor({ 0.0, 1.0, 2.0 }) };
    std::shared_ptr<kp::Tensor> tensorRHS{ new kp::Tensor( { 2.0, 4.0, 6.0 }) };
    std::shared_ptr<kp::Tensor> tensorOutput{ new kp::Tensor({ 0.0, 0.0, 0.0 }) };

    kp::Sequence sq = mgr.constructSequence();
    // Begin recoding commands
    sq.begin();

    // Record sequence of operations to be sent to GPU in batch
    {
        sq.record<kp::OpCreateTensor>({ tensorLHS });
        sq.record<kp::OpCreateTensor>({ tensorRHS });
        sq.record<kp::OpCreateTensor>({ tensorOutput });

        sq.record<kp::OpMult<>>({ tensorLHS, tensorRHS, tensorOutput });
    }
    // Stop recording
    sq.end();
    // Submit operations to GPU
    sq.eval();

    std::cout << fmt::format("Output: {}", tensorOutput.data()) << std::endl;
}

Create your own operation

class CustomOp : kp::OpBase {
    // ...
    void init(std::shared_ptr<Tensor> tensors) {
        // ... extra steps to initialise tensors
        this->mAlgorithm->init("path/to/your/shader.compute.spv", tensors);
    }
}

int main() {
    kp::Manager kManager(); // Chooses device 0 

    kp::Tensor inputOne({0, 1, 2, 3}); 

    kp::Tensor inputTwo({0, 1, 2, 3});

    kp::Tensor output( {0, 0, 0, 0} );
    kManager.eval<kp::CustomOp>({ inputOne, inputTwo, output });

    std::cout << fmt::format("Output: {}", tensorOutput.data()) << std::endl;
}

Kompute Development

  • Follows Mozilla C++ Style Guide https://www-archive.mozilla.org/hacking/mozilla-style-guide.html
    • Uses post-commit hook to run the linter, you can set it up so it runs the linter before commit
  • Uses vcpkg for finding the dependencies, it's the recommanded set up to retrieve the libraries
    • All dependencies are defined in vcpkg.json
  • Uses cmake as build system, and provides a top level makefile with recommended command
  • Uses xxd (or xxd.exe windows 64bit port) to convert shader spirv to header files
Description
General purpose GPU compute framework built on Vulkan to support 1000s of cross vendor graphics cards (AMD, Qualcomm, NVIDIA & friends). Blazing fast, mobile-enabled, asynchronous and optimized for advanced GPU data processing usecases. Backed by the Linux Foundation.
Readme Apache-2.0 18 MiB
Languages
C++ 78.7%
CMake 9.7%
Python 6.7%
Makefile 1.9%
Shell 1.6%
Other 1.4%