Initial implementation of tensor working compiling
This commit is contained in:
parent
b81896a780
commit
ad18c2e546
12 changed files with 417 additions and 210 deletions
|
|
@ -1,4 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.17.0)
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
project(kompute_array_mult VERSION 0.1.0)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
|
|
@ -23,10 +23,6 @@ endif()
|
|||
|
||||
find_package(Vulkan REQUIRED)
|
||||
|
||||
if(KOMPUTE_OPT_ENABLE_SPDLOG)
|
||||
find_package(spdlog REQUIRED)
|
||||
endif()
|
||||
|
||||
add_executable(kompute_array_mult
|
||||
src/Main.cpp)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,8 +15,11 @@ This project has the option to either import the Kompute dependency relative to
|
|||
To build you just need to run the cmake command in this folder as follows:
|
||||
|
||||
```
|
||||
cmake \
|
||||
-Bbuild
|
||||
cmake -Bbuild/ \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DKOMPUTE_OPT_INSTALL=0 \
|
||||
-DKOMPUTE_OPT_REPO_SUBMODULE_BUILD=1 \
|
||||
-DKOMPUTE_OPT_ENABLE_SPDLOG=1
|
||||
```
|
||||
|
||||
You can pass the following optional parameters based on your desired configuration:
|
||||
|
|
|
|||
|
|
@ -7,16 +7,11 @@
|
|||
|
||||
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 });
|
||||
auto tensorInA = mgr.tensor<float>({ 2.0, 4.0, 6.0 });
|
||||
auto tensorInB = mgr.tensor<float>({ 0.0, 1.0, 2.0 });
|
||||
auto tensorOut = mgr.tensor<float>({ 0.0, 0.0, 0.0 });
|
||||
|
||||
std::string shader(R"(
|
||||
// The version to use
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.17.0)
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
project(kompute_linear_reg VERSION 0.1.0)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
|
|
@ -23,10 +23,6 @@ endif()
|
|||
|
||||
find_package(Vulkan REQUIRED)
|
||||
|
||||
if(KOMPUTE_OPT_ENABLE_SPDLOG)
|
||||
find_package(spdlog REQUIRED)
|
||||
endif()
|
||||
|
||||
add_executable(kompute_linear_reg
|
||||
src/Main.cpp)
|
||||
|
||||
|
|
@ -39,7 +35,7 @@ include_directories(
|
|||
../../single_include/)
|
||||
|
||||
if(KOMPUTE_OPT_ENABLE_SPDLOG)
|
||||
target_link_libraries(kompute_array_mult
|
||||
target_link_libraries(kompute_linear_reg
|
||||
spdlog::spdlog)
|
||||
endif()
|
||||
|
||||
|
|
|
|||
|
|
@ -15,8 +15,11 @@ This project has the option to either import the Kompute dependency relative to
|
|||
To build you just need to run the cmake command in this folder as follows:
|
||||
|
||||
```
|
||||
cmake \
|
||||
-Bbuild
|
||||
cmake -Bbuild/ \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DKOMPUTE_OPT_INSTALL=0 \
|
||||
-DKOMPUTE_OPT_REPO_SUBMODULE_BUILD=1 \
|
||||
-DKOMPUTE_OPT_ENABLE_SPDLOG=1
|
||||
```
|
||||
|
||||
You can pass the following optional parameters based on your desired configuration:
|
||||
|
|
|
|||
|
|
@ -17,19 +17,19 @@ int main()
|
|||
|
||||
kp::Manager mgr;
|
||||
|
||||
std::shared_ptr<kp::Tensor> xI = mgr.tensor({ 0, 1, 1, 1, 1 });
|
||||
std::shared_ptr<kp::Tensor> xJ = mgr.tensor({ 0, 0, 0, 1, 1 });
|
||||
auto xI = mgr.tensor<float>({ 0, 1, 1, 1, 1 });
|
||||
auto xJ = mgr.tensor<float>({ 0, 0, 0, 1, 1 });
|
||||
|
||||
std::shared_ptr<kp::Tensor> y = mgr.tensor({ 0, 0, 0, 1, 1 });
|
||||
auto y = mgr.tensor<float>({ 0, 0, 0, 1, 1 });
|
||||
|
||||
std::shared_ptr<kp::Tensor> wIn = mgr.tensor({ 0.001, 0.001 });
|
||||
std::shared_ptr<kp::Tensor> wOutI = mgr.tensor({ 0, 0, 0, 0, 0 });
|
||||
std::shared_ptr<kp::Tensor> wOutJ = mgr.tensor({ 0, 0, 0, 0, 0 });
|
||||
auto wIn = mgr.tensor<float>({ 0.001, 0.001 });
|
||||
auto wOutI = mgr.tensor<float>({ 0, 0, 0, 0, 0 });
|
||||
auto wOutJ = mgr.tensor<float>({ 0, 0, 0, 0, 0 });
|
||||
|
||||
std::shared_ptr<kp::Tensor> bIn = mgr.tensor({ 0 });
|
||||
std::shared_ptr<kp::Tensor> bOut = mgr.tensor({ 0, 0, 0, 0, 0 });
|
||||
auto bIn = mgr.tensor<float>({ 0 });
|
||||
auto bOut = mgr.tensor<float>({ 0, 0, 0, 0, 0 });
|
||||
|
||||
std::shared_ptr<kp::Tensor> lOut = mgr.tensor({ 0, 0, 0, 0, 0 });
|
||||
auto lOut = mgr.tensor<float>({ 0, 0, 0, 0, 0 });
|
||||
|
||||
std::vector<std::shared_ptr<kp::Tensor>> params = { xI, xJ, y,
|
||||
wIn, wOutI, wOutJ,
|
||||
|
|
|
|||
|
|
@ -762,7 +762,7 @@ class Shader
|
|||
* GLSL compiler
|
||||
* @return The compiled SPIR-V binary in unsigned int32 format
|
||||
*/
|
||||
static std::vector<uint32_t> compileSources(
|
||||
static std::vector<uint32_t> compile_sources(
|
||||
const std::vector<std::string>& sources,
|
||||
const std::vector<std::string>& files = {},
|
||||
const std::string& entryPoint = "main",
|
||||
|
|
@ -783,7 +783,7 @@ class Shader
|
|||
* GLSL compiler
|
||||
* @return The compiled SPIR-V binary in unsigned int32 format
|
||||
*/
|
||||
static std::vector<uint32_t> compileSource(
|
||||
static std::vector<uint32_t> compile_source(
|
||||
const std::string& source,
|
||||
const std::string& entryPoint = "main",
|
||||
std::vector<std::pair<std::string, std::string>> definitions = {},
|
||||
|
|
@ -818,6 +818,14 @@ class Tensor
|
|||
eHost = 1, ///< Type is host memory, source and destination
|
||||
eStorage = 2, ///< Type is Device memory (only)
|
||||
};
|
||||
enum class TensorDataTypes
|
||||
{
|
||||
eBool = 0,
|
||||
eInt = 1,
|
||||
eUnsignedInt = 2,
|
||||
eFloat = 3,
|
||||
eDouble = 4,
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor with data provided which would be used to create the
|
||||
|
|
@ -831,14 +839,78 @@ class Tensor
|
|||
*/
|
||||
Tensor(std::shared_ptr<vk::PhysicalDevice> physicalDevice,
|
||||
std::shared_ptr<vk::Device> device,
|
||||
const std::vector<float>& data,
|
||||
void* data,
|
||||
uint32_t elementTotalCount,
|
||||
uint32_t elementMemorySize,
|
||||
const TensorDataTypes& dataType,
|
||||
const TensorTypes& tensorType = TensorTypes::eDevice);
|
||||
|
||||
/**
|
||||
* Destructor which is in charge of freeing vulkan resources unless they
|
||||
* have been provided externally.
|
||||
*/
|
||||
~Tensor();
|
||||
virtual ~Tensor();
|
||||
|
||||
/**
|
||||
* Returns the size/magnitude of the Tensor, which will be the total number
|
||||
* of elements across all dimensions
|
||||
*
|
||||
* @return Unsigned integer representing the total number of elements
|
||||
*/
|
||||
// TODO: move to cpp
|
||||
virtual uint32_t size() {
|
||||
return this->mSize;
|
||||
}
|
||||
|
||||
// TODO: move to cpp
|
||||
virtual uint32_t dataTypeMemorySize() {
|
||||
return this->mDataTypeMemorySize;
|
||||
}
|
||||
|
||||
// TODO: move to cpp
|
||||
virtual uint32_t memorySize() {
|
||||
return this->mSize * this->mDataTypeMemorySize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the underlying data type of the Tensor
|
||||
*
|
||||
* @return Data type of tensor of type kp::Tensor::TensorDataTypes
|
||||
*/
|
||||
virtual TensorDataTypes dataType() {
|
||||
return this->mDataType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps data from the Host Visible GPU memory into the data vector. It
|
||||
* requires the Tensor to be of staging type for it to work.
|
||||
*/
|
||||
virtual void mapDataFromHostMemory();
|
||||
/**
|
||||
* Maps data from the data vector into the Host Visible GPU memory. It
|
||||
* requires the tensor to be of staging type for it to work.
|
||||
*/
|
||||
virtual void mapDataIntoHostMemory();
|
||||
|
||||
// TODO: Decide whether this is one we prefer to have also overriden in the underlying tensorView
|
||||
// TODO: move to cpp
|
||||
virtual void getRawData(void* data) {
|
||||
this->rawMapDataFromHostMemory(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets / resets the vector data of the tensor. This function does not
|
||||
* perform any copies into GPU memory and is only performed on the host.
|
||||
*/
|
||||
virtual void setRawData(void* data, uint32_t elementTotalCount, uint32_t elementMemorySize) {
|
||||
if (elementTotalCount * elementMemorySize != this->memorySize()) {
|
||||
throw std::runtime_error(
|
||||
"Kompute Tensor Cannot set data of different sizes");
|
||||
}
|
||||
this->mSize = elementTotalCount;
|
||||
this->mDataTypeMemorySize = elementMemorySize;
|
||||
this->rawMapDataIntoHostMemory(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to trigger reinitialisation of the tensor buffer and memory with
|
||||
|
|
@ -847,8 +919,9 @@ class Tensor
|
|||
* @param data Vector of data to use to initialise vector from
|
||||
* @param tensorType The type to use for the tensor
|
||||
*/
|
||||
void rebuild(const std::vector<float>& data,
|
||||
TensorTypes tensorType = TensorTypes::eDevice);
|
||||
void rebuild(void* data,
|
||||
uint32_t elementTotalCount,
|
||||
uint32_t elementMemorySize);
|
||||
|
||||
/**
|
||||
* Destroys and frees the GPU resources which include the buffer and memory.
|
||||
|
|
@ -862,32 +935,6 @@ class Tensor
|
|||
*/
|
||||
bool isInit();
|
||||
|
||||
/**
|
||||
* Returns the vector of data currently contained by the Tensor. It is
|
||||
* important to ensure that there is no out-of-sync data with the GPU
|
||||
* memory.
|
||||
*
|
||||
* @return Reference to vector of elements representing the data in the
|
||||
* tensor.
|
||||
*/
|
||||
std::vector<float>& data();
|
||||
/**
|
||||
* Overrides the subscript operator to expose the underlying data's
|
||||
* subscript operator which in this case would be its underlying
|
||||
* vector's.
|
||||
*
|
||||
* @param i The index where the element will be returned from.
|
||||
* @return Returns the element in the position requested.
|
||||
*/
|
||||
float& operator[](int index);
|
||||
/**
|
||||
* Returns the size/magnitude of the Tensor, which will be the total number
|
||||
* of elements across all dimensions
|
||||
*
|
||||
* @return Unsigned integer representing the total number of elements
|
||||
*/
|
||||
uint32_t size();
|
||||
|
||||
/**
|
||||
* Retrieve the tensor type of the Tensor
|
||||
*
|
||||
|
|
@ -895,12 +942,6 @@ class Tensor
|
|||
*/
|
||||
TensorTypes tensorType();
|
||||
|
||||
/**
|
||||
* Sets / resets the vector data of the tensor. This function does not
|
||||
* perform any copies into GPU memory and is only performed on the host.
|
||||
*/
|
||||
void setData(const std::vector<float>& data);
|
||||
|
||||
/**
|
||||
* Records a copy from the memory of the tensor provided to the current
|
||||
* thensor. This is intended to pass memory into a processing, to perform
|
||||
|
|
@ -963,17 +1004,57 @@ class Tensor
|
|||
* @return Descriptor buffer info with own buffer
|
||||
*/
|
||||
vk::DescriptorBufferInfo constructDescriptorBufferInfo();
|
||||
/**
|
||||
* Maps data from the Host Visible GPU memory into the data vector. It
|
||||
* requires the Tensor to be of staging type for it to work.
|
||||
*/
|
||||
void mapDataFromHostMemory();
|
||||
/**
|
||||
* Maps data from the data vector into the Host Visible GPU memory. It
|
||||
* requires the tensor to be of staging type for it to work.
|
||||
*/
|
||||
void mapDataIntoHostMemory();
|
||||
|
||||
protected:
|
||||
void rawMapDataFromHostMemory(void* data) {
|
||||
|
||||
KP_LOG_DEBUG("Kompute Tensor mapping data from host buffer");
|
||||
|
||||
std::shared_ptr<vk::DeviceMemory> hostVisibleMemory = nullptr;
|
||||
|
||||
if (this->mTensorType == TensorTypes::eHost) {
|
||||
hostVisibleMemory = this->mPrimaryMemory;
|
||||
} else if (this->mTensorType == TensorTypes::eDevice) {
|
||||
hostVisibleMemory = this->mStagingMemory;
|
||||
} else {
|
||||
KP_LOG_WARN(
|
||||
"Kompute Tensor mapping data not supported on storage tensor");
|
||||
return;
|
||||
}
|
||||
|
||||
vk::DeviceSize bufferSize = this->memorySize();
|
||||
void* mapped = this->mDevice->mapMemory(
|
||||
*hostVisibleMemory, 0, bufferSize, vk::MemoryMapFlags());
|
||||
vk::MappedMemoryRange mappedMemoryRange(*hostVisibleMemory, 0, bufferSize);
|
||||
this->mDevice->invalidateMappedMemoryRanges(mappedMemoryRange);
|
||||
memcpy(data, mapped, bufferSize);
|
||||
this->mDevice->unmapMemory(*hostVisibleMemory);
|
||||
}
|
||||
|
||||
void rawMapDataIntoHostMemory(void* data) {
|
||||
KP_LOG_DEBUG("Kompute Tensor mapping data into host buffer");
|
||||
|
||||
std::shared_ptr<vk::DeviceMemory> hostVisibleMemory = nullptr;
|
||||
|
||||
if (this->mTensorType == TensorTypes::eHost) {
|
||||
hostVisibleMemory = this->mPrimaryMemory;
|
||||
} else if (this->mTensorType == TensorTypes::eDevice) {
|
||||
hostVisibleMemory = this->mStagingMemory;
|
||||
} else {
|
||||
KP_LOG_WARN(
|
||||
"Kompute Tensor mapping data not supported on storage tensor");
|
||||
return;
|
||||
}
|
||||
|
||||
vk::DeviceSize bufferSize = this->memorySize();
|
||||
|
||||
void* mapped = this->mDevice->mapMemory(
|
||||
*hostVisibleMemory, 0, bufferSize, vk::MemoryMapFlags());
|
||||
memcpy(mapped, data, bufferSize);
|
||||
vk::MappedMemoryRange mappedRange(*hostVisibleMemory, 0, bufferSize);
|
||||
this->mDevice->flushMappedMemoryRanges(1, &mappedRange);
|
||||
this->mDevice->unmapMemory(*hostVisibleMemory);
|
||||
}
|
||||
private:
|
||||
// -------------- NEVER OWNED RESOURCES
|
||||
std::shared_ptr<vk::PhysicalDevice> mPhysicalDevice;
|
||||
|
|
@ -990,9 +1071,10 @@ class Tensor
|
|||
bool mFreeStagingMemory = false;
|
||||
|
||||
// -------------- ALWAYS OWNED RESOURCES
|
||||
std::vector<float> mData;
|
||||
|
||||
TensorTypes mTensorType = TensorTypes::eDevice;
|
||||
TensorTypes mTensorType;
|
||||
TensorDataTypes mDataType;
|
||||
uint32_t mSize;
|
||||
uint32_t mDataTypeMemorySize;
|
||||
|
||||
void allocateMemoryCreateGPUResources(); // Creates the vulkan buffer
|
||||
void createBuffer(std::shared_ptr<vk::Buffer> buffer,
|
||||
|
|
@ -1012,9 +1094,98 @@ class Tensor
|
|||
vk::MemoryPropertyFlags getPrimaryMemoryPropertyFlags();
|
||||
vk::BufferUsageFlags getStagingBufferUsageFlags();
|
||||
vk::MemoryPropertyFlags getStagingMemoryPropertyFlags();
|
||||
uint64_t memorySize();
|
||||
|
||||
};
|
||||
|
||||
// TODO: Limit T to be only float, bool, double, etc
|
||||
template <typename T>
|
||||
class TensorView: public Tensor
|
||||
{
|
||||
public:
|
||||
TensorView(std::shared_ptr<vk::PhysicalDevice> physicalDevice,
|
||||
std::shared_ptr<vk::Device> device,
|
||||
const std::vector<T>& data,
|
||||
const TensorTypes& tensorType = TensorTypes::eDevice)
|
||||
: Tensor(physicalDevice, device, (void*)data.data(), data.size(), sizeof(T), this->dataType())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
~TensorView() {
|
||||
|
||||
}
|
||||
|
||||
void rebuild(const std::vector<T>& data,
|
||||
TensorTypes tensorType = TensorTypes::eDevice) {
|
||||
|
||||
this->mData = data;
|
||||
Tensor::rebuild(data.data(), data.size(), sizeof(T));
|
||||
}
|
||||
|
||||
std::vector<T>& data() {
|
||||
return this->mData;
|
||||
}
|
||||
|
||||
T& operator[](int index) {
|
||||
return this->mData[index];
|
||||
}
|
||||
|
||||
void setData(const std::vector<T>& data) {
|
||||
|
||||
if (data.size() != this->mData.size()) {
|
||||
throw std::runtime_error(
|
||||
"Kompute TensorView Cannot set data of different sizes");
|
||||
}
|
||||
|
||||
this->mData = data;
|
||||
|
||||
Tensor::setRawData(this->mData.data(), this->mData.size(), sizeof(T));
|
||||
}
|
||||
|
||||
void setRawData(void* data, uint32_t elementTotalCount, uint32_t elementMemorySize) override
|
||||
{
|
||||
assert(elementMemorySize == sizeof(T));
|
||||
|
||||
this->mData = { (T*)data, ((T*)data) + elementTotalCount };
|
||||
Tensor::setRawData(this->mData.data(), this->mData.size(), sizeof(T));
|
||||
}
|
||||
|
||||
TensorDataTypes dataType() override;
|
||||
|
||||
uint32_t size() override {
|
||||
return this->mData.size();
|
||||
}
|
||||
|
||||
uint32_t memorySize() override {
|
||||
return this->mData.size() * sizeof(T);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps data from the Host Visible GPU memory into the data vector. It
|
||||
* requires the Tensor to be of staging type for it to work.
|
||||
*/
|
||||
void mapDataFromHostMemory() override {
|
||||
KP_LOG_DEBUG("Kompute TensorView mapDataFromHostMemory copying data");
|
||||
|
||||
this->rawMapDataFromHostMemory(this->mData.data());
|
||||
}
|
||||
/**
|
||||
* Maps data from the data vector into the Host Visible GPU memory. It
|
||||
* requires the tensor to be of staging type for it to work.
|
||||
*/
|
||||
void mapDataIntoHostMemory() override {
|
||||
KP_LOG_DEBUG("Kompute TensorView mapDataIntoHostMemory copying data");
|
||||
|
||||
this->rawMapDataIntoHostMemory(this->mData.data());
|
||||
}
|
||||
|
||||
private:
|
||||
// -------------- ALWAYS OWNED RESOURCES
|
||||
std::vector<T> mData;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // End namespace kp
|
||||
|
||||
namespace kp {
|
||||
|
|
@ -1883,9 +2054,22 @@ class Manager
|
|||
* @param tensorType The type of tensor to initialize
|
||||
* @returns Shared pointer with initialised tensor
|
||||
*/
|
||||
std::shared_ptr<Tensor> tensor(
|
||||
const std::vector<float>& data,
|
||||
Tensor::TensorTypes tensorType = Tensor::TensorTypes::eDevice);
|
||||
template <typename T>
|
||||
std::shared_ptr<TensorView<T>> tensor(
|
||||
const std::vector<T>& data,
|
||||
Tensor::TensorTypes tensorType = Tensor::TensorTypes::eDevice)
|
||||
{
|
||||
KP_LOG_DEBUG("Kompute Manager tensor creation triggered");
|
||||
|
||||
std::shared_ptr<TensorView<T>> tensor{ new kp::TensorView<T>(
|
||||
this->mPhysicalDevice, this->mDevice, data, tensorType) };
|
||||
|
||||
if (this->mManageResources) {
|
||||
this->mManagedTensors.push_back(tensor);
|
||||
}
|
||||
|
||||
return tensor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a managed algorithm that will be destroyed by this manager
|
||||
|
|
|
|||
|
|
@ -395,21 +395,6 @@ Manager::createDevice(const std::vector<uint32_t>& familyQueueIndices,
|
|||
KP_LOG_DEBUG("Kompute Manager compute queue obtained");
|
||||
}
|
||||
|
||||
std::shared_ptr<Tensor>
|
||||
Manager::tensor(const std::vector<float>& data, Tensor::TensorTypes tensorType)
|
||||
{
|
||||
KP_LOG_DEBUG("Kompute Manager tensor creation triggered");
|
||||
|
||||
std::shared_ptr<Tensor> tensor{ new kp::Tensor(
|
||||
this->mPhysicalDevice, this->mDevice, data, tensorType) };
|
||||
|
||||
if (this->mManageResources) {
|
||||
this->mManagedTensors.push_back(tensor);
|
||||
}
|
||||
|
||||
return tensor;
|
||||
}
|
||||
|
||||
std::shared_ptr<Algorithm>
|
||||
Manager::algorithm(const std::vector<std::shared_ptr<Tensor>>& tensors,
|
||||
const std::vector<uint32_t>& spirv,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,14 @@ OpTensorCopy::OpTensorCopy(const std::vector<std::shared_ptr<Tensor>>& tensors)
|
|||
throw std::runtime_error(
|
||||
"Kompute OpTensorCopy called with less than 2 tensor");
|
||||
}
|
||||
|
||||
kp::Tensor::TensorDataTypes dataType = this->mTensors[0]->dataType();
|
||||
for (const std::shared_ptr<Tensor>& tensor : tensors) {
|
||||
if (tensor->dataType() != dataType) {
|
||||
throw std::runtime_error(fmt::format("Attempting to copy tensors of different types from {} to {}",
|
||||
dataType, tensor->dataType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OpTensorCopy::~OpTensorCopy()
|
||||
|
|
@ -43,9 +51,16 @@ OpTensorCopy::postEval(const vk::CommandBuffer& commandBuffer)
|
|||
{
|
||||
KP_LOG_DEBUG("Kompute OpTensorCopy postEval called");
|
||||
|
||||
// TODO: Simplify with a copyRawData
|
||||
uint32_t size = this->mTensors[0]->size();
|
||||
uint32_t dataTypeMemSize = this->mTensors[0]->dataTypeMemorySize();
|
||||
uint32_t memSize = size * dataTypeMemSize;
|
||||
void* data = operator new(memSize);
|
||||
this->mTensors[0]->getRawData(data);
|
||||
|
||||
// Copy the data from the first tensor into all the tensors
|
||||
for (size_t i = 1; i < this->mTensors.size(); i++) {
|
||||
this->mTensors[i]->setData(this->mTensors[0]->data());
|
||||
this->mTensors[i]->setRawData(data, size, dataTypeMemSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,8 +17,10 @@ Tensor::Tensor(std::shared_ptr<vk::PhysicalDevice> physicalDevice,
|
|||
|
||||
this->mPhysicalDevice = physicalDevice;
|
||||
this->mDevice = device;
|
||||
this->mDataType = dataType;
|
||||
this->mTensorType = tensorType;
|
||||
|
||||
this->rebuild(data, elementTotalCount, elementMemorySize, dataType, tensorType);
|
||||
this->rebuild(data, elementTotalCount, elementMemorySize);
|
||||
}
|
||||
|
||||
Tensor::~Tensor()
|
||||
|
|
@ -34,16 +36,12 @@ Tensor::~Tensor()
|
|||
void
|
||||
Tensor::rebuild(void* data,
|
||||
uint32_t elementTotalCount,
|
||||
uint32_t elementMemorySize,
|
||||
const TensorDataTypes& dataType,
|
||||
TensorTypes tensorType)
|
||||
uint32_t elementMemorySize)
|
||||
{
|
||||
KP_LOG_DEBUG("Kompute Tensor rebuilding with size {}", elementTotalCount);
|
||||
|
||||
this->mSize = elementTotalCount;
|
||||
this->mElementMemorySize = elementMemorySize;
|
||||
this->mDataType = dataType;
|
||||
this->mTensorType = tensorType;
|
||||
this->mDataTypeMemorySize = elementMemorySize;
|
||||
|
||||
if (this->mPrimaryBuffer || this->mPrimaryMemory) {
|
||||
KP_LOG_DEBUG(
|
||||
|
|
@ -439,4 +437,34 @@ Tensor::destroy()
|
|||
KP_LOG_DEBUG("Kompute Tensor successful destroy()");
|
||||
}
|
||||
|
||||
template<>
|
||||
Tensor::TensorDataTypes
|
||||
TensorView<bool>::dataType() {
|
||||
return Tensor::TensorDataTypes::eBool;
|
||||
}
|
||||
|
||||
template<>
|
||||
Tensor::TensorDataTypes
|
||||
TensorView<int32_t>::dataType() {
|
||||
return Tensor::TensorDataTypes::eInt;
|
||||
}
|
||||
|
||||
template<>
|
||||
Tensor::TensorDataTypes
|
||||
TensorView<uint32_t>::dataType() {
|
||||
return Tensor::TensorDataTypes::eUnsignedInt;
|
||||
}
|
||||
|
||||
template<>
|
||||
Tensor::TensorDataTypes
|
||||
TensorView<float>::dataType() {
|
||||
return Tensor::TensorDataTypes::eFloat;
|
||||
}
|
||||
|
||||
template<>
|
||||
Tensor::TensorDataTypes
|
||||
TensorView<double>::dataType() {
|
||||
return Tensor::TensorDataTypes::eDouble;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,9 +74,22 @@ class Manager
|
|||
* @param tensorType The type of tensor to initialize
|
||||
* @returns Shared pointer with initialised tensor
|
||||
*/
|
||||
std::shared_ptr<Tensor> tensor(
|
||||
const std::vector<float>& data,
|
||||
Tensor::TensorTypes tensorType = Tensor::TensorTypes::eDevice);
|
||||
template <typename T>
|
||||
std::shared_ptr<TensorView<T>> tensor(
|
||||
const std::vector<T>& data,
|
||||
Tensor::TensorTypes tensorType = Tensor::TensorTypes::eDevice)
|
||||
{
|
||||
KP_LOG_DEBUG("Kompute Manager tensor creation triggered");
|
||||
|
||||
std::shared_ptr<TensorView<T>> tensor{ new kp::TensorView<T>(
|
||||
this->mPhysicalDevice, this->mDevice, data, tensorType) };
|
||||
|
||||
if (this->mManageResources) {
|
||||
this->mManagedTensors.push_back(tensor);
|
||||
}
|
||||
|
||||
return tensor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a managed algorithm that will be destroyed by this manager
|
||||
|
|
|
|||
|
|
@ -51,14 +51,14 @@ class Tensor
|
|||
void* data,
|
||||
uint32_t elementTotalCount,
|
||||
uint32_t elementMemorySize,
|
||||
const TensorDataTypes& dataType = TensorDataTypes::eFloat,
|
||||
const TensorDataTypes& dataType,
|
||||
const TensorTypes& tensorType = TensorTypes::eDevice);
|
||||
|
||||
/**
|
||||
* Destructor which is in charge of freeing vulkan resources unless they
|
||||
* have been provided externally.
|
||||
*/
|
||||
~Tensor();
|
||||
virtual ~Tensor();
|
||||
|
||||
/**
|
||||
* Returns the size/magnitude of the Tensor, which will be the total number
|
||||
|
|
@ -68,12 +68,17 @@ class Tensor
|
|||
*/
|
||||
// TODO: move to cpp
|
||||
virtual uint32_t size() {
|
||||
return this->mElementMemorySize;
|
||||
return this->mSize;
|
||||
}
|
||||
|
||||
// TODO: move to cpp
|
||||
virtual uint32_t dataTypeMemorySize() {
|
||||
return this->mDataTypeMemorySize;
|
||||
}
|
||||
|
||||
// TODO: move to cpp
|
||||
virtual uint32_t memorySize() {
|
||||
return this->mSize * this->mElementMemorySize;
|
||||
return this->mSize * this->mDataTypeMemorySize;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -98,10 +103,24 @@ class Tensor
|
|||
|
||||
// TODO: Decide whether this is one we prefer to have also overriden in the underlying tensorView
|
||||
// TODO: move to cpp
|
||||
void getRawData(void* data) {
|
||||
virtual void getRawData(void* data) {
|
||||
this->rawMapDataFromHostMemory(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets / resets the vector data of the tensor. This function does not
|
||||
* perform any copies into GPU memory and is only performed on the host.
|
||||
*/
|
||||
virtual void setRawData(void* data, uint32_t elementTotalCount, uint32_t elementMemorySize) {
|
||||
if (elementTotalCount * elementMemorySize != this->memorySize()) {
|
||||
throw std::runtime_error(
|
||||
"Kompute Tensor Cannot set data of different sizes");
|
||||
}
|
||||
this->mSize = elementTotalCount;
|
||||
this->mDataTypeMemorySize = elementMemorySize;
|
||||
this->rawMapDataIntoHostMemory(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to trigger reinitialisation of the tensor buffer and memory with
|
||||
* new data as well as new potential device type.
|
||||
|
|
@ -111,9 +130,7 @@ class Tensor
|
|||
*/
|
||||
void rebuild(void* data,
|
||||
uint32_t elementTotalCount,
|
||||
uint32_t elementMemorySize,
|
||||
const TensorDataTypes& dataType = TensorDataTypes::eFloat,
|
||||
TensorTypes tensorType = TensorTypes::eDevice);
|
||||
uint32_t elementMemorySize);
|
||||
|
||||
/**
|
||||
* Destroys and frees the GPU resources which include the buffer and memory.
|
||||
|
|
@ -134,19 +151,6 @@ class Tensor
|
|||
*/
|
||||
TensorTypes tensorType();
|
||||
|
||||
/**
|
||||
* Sets / resets the vector data of the tensor. This function does not
|
||||
* perform any copies into GPU memory and is only performed on the host.
|
||||
*/
|
||||
void setRawData(void* data, uint32_t elementTotalCount, uint32_t elementMemorySize) {
|
||||
if (elementTotalCount * elementMemorySize != this->memorySize()) {
|
||||
throw std::runtime_error(
|
||||
"Kompute Tensor Cannot set data of different sizes");
|
||||
}
|
||||
this->mSize = elementTotalCount;
|
||||
this->mElementMemorySize = elementMemorySize;
|
||||
this->rawMapDataIntoHostMemory(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Records a copy from the memory of the tensor provided to the current
|
||||
|
|
@ -211,46 +215,7 @@ class Tensor
|
|||
*/
|
||||
vk::DescriptorBufferInfo constructDescriptorBufferInfo();
|
||||
|
||||
private:
|
||||
// -------------- NEVER OWNED RESOURCES
|
||||
std::shared_ptr<vk::PhysicalDevice> mPhysicalDevice;
|
||||
std::shared_ptr<vk::Device> mDevice;
|
||||
|
||||
// -------------- OPTIONALLY OWNED RESOURCES
|
||||
std::shared_ptr<vk::Buffer> mPrimaryBuffer;
|
||||
bool mFreePrimaryBuffer = false;
|
||||
std::shared_ptr<vk::Buffer> mStagingBuffer;
|
||||
bool mFreeStagingBuffer = false;
|
||||
std::shared_ptr<vk::DeviceMemory> mPrimaryMemory;
|
||||
bool mFreePrimaryMemory = false;
|
||||
std::shared_ptr<vk::DeviceMemory> mStagingMemory;
|
||||
bool mFreeStagingMemory = false;
|
||||
|
||||
// -------------- ALWAYS OWNED RESOURCES
|
||||
TensorTypes mTensorType;
|
||||
TensorDataTypes mDataType;
|
||||
uint32_t mSize;
|
||||
uint32_t mElementMemorySize;
|
||||
|
||||
void allocateMemoryCreateGPUResources(); // Creates the vulkan buffer
|
||||
void createBuffer(std::shared_ptr<vk::Buffer> buffer,
|
||||
vk::BufferUsageFlags bufferUsageFlags);
|
||||
void allocateBindMemory(std::shared_ptr<vk::Buffer> buffer,
|
||||
std::shared_ptr<vk::DeviceMemory> memory,
|
||||
vk::MemoryPropertyFlags memoryPropertyFlags);
|
||||
void recordCopyBuffer(const vk::CommandBuffer& commandBuffer,
|
||||
std::shared_ptr<vk::Buffer> bufferFrom,
|
||||
std::shared_ptr<vk::Buffer> bufferTo,
|
||||
vk::DeviceSize bufferSize,
|
||||
vk::BufferCopy copyRegion,
|
||||
bool createBarrier);
|
||||
|
||||
// Private util functions
|
||||
vk::BufferUsageFlags getPrimaryBufferUsageFlags();
|
||||
vk::MemoryPropertyFlags getPrimaryMemoryPropertyFlags();
|
||||
vk::BufferUsageFlags getStagingBufferUsageFlags();
|
||||
vk::MemoryPropertyFlags getStagingMemoryPropertyFlags();
|
||||
|
||||
protected:
|
||||
void rawMapDataFromHostMemory(void* data) {
|
||||
|
||||
KP_LOG_DEBUG("Kompute Tensor mapping data from host buffer");
|
||||
|
|
@ -300,6 +265,46 @@ class Tensor
|
|||
this->mDevice->flushMappedMemoryRanges(1, &mappedRange);
|
||||
this->mDevice->unmapMemory(*hostVisibleMemory);
|
||||
}
|
||||
private:
|
||||
// -------------- NEVER OWNED RESOURCES
|
||||
std::shared_ptr<vk::PhysicalDevice> mPhysicalDevice;
|
||||
std::shared_ptr<vk::Device> mDevice;
|
||||
|
||||
// -------------- OPTIONALLY OWNED RESOURCES
|
||||
std::shared_ptr<vk::Buffer> mPrimaryBuffer;
|
||||
bool mFreePrimaryBuffer = false;
|
||||
std::shared_ptr<vk::Buffer> mStagingBuffer;
|
||||
bool mFreeStagingBuffer = false;
|
||||
std::shared_ptr<vk::DeviceMemory> mPrimaryMemory;
|
||||
bool mFreePrimaryMemory = false;
|
||||
std::shared_ptr<vk::DeviceMemory> mStagingMemory;
|
||||
bool mFreeStagingMemory = false;
|
||||
|
||||
// -------------- ALWAYS OWNED RESOURCES
|
||||
TensorTypes mTensorType;
|
||||
TensorDataTypes mDataType;
|
||||
uint32_t mSize;
|
||||
uint32_t mDataTypeMemorySize;
|
||||
|
||||
void allocateMemoryCreateGPUResources(); // Creates the vulkan buffer
|
||||
void createBuffer(std::shared_ptr<vk::Buffer> buffer,
|
||||
vk::BufferUsageFlags bufferUsageFlags);
|
||||
void allocateBindMemory(std::shared_ptr<vk::Buffer> buffer,
|
||||
std::shared_ptr<vk::DeviceMemory> memory,
|
||||
vk::MemoryPropertyFlags memoryPropertyFlags);
|
||||
void recordCopyBuffer(const vk::CommandBuffer& commandBuffer,
|
||||
std::shared_ptr<vk::Buffer> bufferFrom,
|
||||
std::shared_ptr<vk::Buffer> bufferTo,
|
||||
vk::DeviceSize bufferSize,
|
||||
vk::BufferCopy copyRegion,
|
||||
bool createBarrier);
|
||||
|
||||
// Private util functions
|
||||
vk::BufferUsageFlags getPrimaryBufferUsageFlags();
|
||||
vk::MemoryPropertyFlags getPrimaryMemoryPropertyFlags();
|
||||
vk::BufferUsageFlags getStagingBufferUsageFlags();
|
||||
vk::MemoryPropertyFlags getStagingMemoryPropertyFlags();
|
||||
|
||||
};
|
||||
|
||||
// TODO: Limit T to be only float, bool, double, etc
|
||||
|
|
@ -310,15 +315,21 @@ class TensorView: public Tensor
|
|||
TensorView(std::shared_ptr<vk::PhysicalDevice> physicalDevice,
|
||||
std::shared_ptr<vk::Device> device,
|
||||
const std::vector<T>& data,
|
||||
const TensorTypes& tensorType = TensorTypes::eDevice);
|
||||
const TensorTypes& tensorType = TensorTypes::eDevice)
|
||||
: Tensor(physicalDevice, device, (void*)data.data(), data.size(), sizeof(T), this->dataType())
|
||||
{
|
||||
|
||||
~TensorView();
|
||||
}
|
||||
|
||||
~TensorView() {
|
||||
|
||||
}
|
||||
|
||||
void rebuild(const std::vector<T>& data,
|
||||
TensorTypes tensorType = TensorTypes::eDevice) {
|
||||
|
||||
this->mData = data;
|
||||
Tensor::rebuild(data.data(), data.size(), sizeof(T), this->dataType(), tensorType);
|
||||
Tensor::rebuild(data.data(), data.size(), sizeof(T));
|
||||
}
|
||||
|
||||
std::vector<T>& data() {
|
||||
|
|
@ -338,17 +349,25 @@ class TensorView: public Tensor
|
|||
|
||||
this->mData = data;
|
||||
|
||||
this->setRawData(this->mData.data(), this->mData.size(), sizeof(T), this->dataType());
|
||||
Tensor::setRawData(this->mData.data(), this->mData.size(), sizeof(T));
|
||||
}
|
||||
|
||||
void setRawData(void* data, uint32_t elementTotalCount, uint32_t elementMemorySize) override
|
||||
{
|
||||
assert(elementMemorySize == sizeof(T));
|
||||
|
||||
this->mData = { (T*)data, ((T*)data) + elementTotalCount };
|
||||
Tensor::setRawData(this->mData.data(), this->mData.size(), sizeof(T));
|
||||
}
|
||||
|
||||
TensorDataTypes dataType() override;
|
||||
|
||||
uint32_t size() override {
|
||||
return this->mData->size();
|
||||
return this->mData.size();
|
||||
}
|
||||
|
||||
uint32_t memorySize() override {
|
||||
return this->mData->size() * sizeof(T);
|
||||
return this->mData.size() * sizeof(T);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -376,34 +395,4 @@ class TensorView: public Tensor
|
|||
|
||||
};
|
||||
|
||||
template<>
|
||||
Tensor::TensorDataTypes
|
||||
TensorView<bool>::dataType() {
|
||||
return Tensor::TensorDataTypes::eBool;
|
||||
}
|
||||
|
||||
template<>
|
||||
Tensor::TensorDataTypes
|
||||
TensorView<int32_t>::dataType() {
|
||||
return Tensor::TensorDataTypes::eInt;
|
||||
}
|
||||
|
||||
template<>
|
||||
Tensor::TensorDataTypes
|
||||
TensorView<uint32_t>::dataType() {
|
||||
return Tensor::TensorDataTypes::eUnsignedInt;
|
||||
}
|
||||
|
||||
template<>
|
||||
Tensor::TensorDataTypes
|
||||
TensorView<float>::dataType() {
|
||||
return Tensor::TensorDataTypes::eFloat;
|
||||
}
|
||||
|
||||
template<>
|
||||
Tensor::TensorDataTypes
|
||||
TensorView<double>::dataType() {
|
||||
return Tensor::TensorDataTypes::eDouble;
|
||||
}
|
||||
|
||||
} // End namespace kp
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue