Updated tests and rebased
This commit is contained in:
parent
bb64b2b37c
commit
a2ee928f4c
9 changed files with 151 additions and 100 deletions
|
|
@ -92,59 +92,46 @@ PYBIND11_MODULE(kp, m) {
|
|||
|
||||
py::class_<kp::Tensor, std::shared_ptr<kp::Tensor>>(m, "Tensor", DOC(kp, Tensor))
|
||||
.def("data", [](kp::Tensor& self) {
|
||||
return py::array(self.data().size(), self.data().data());
|
||||
}, DOC(kp, Tensor, data))
|
||||
.def("__getitem__", [](kp::Tensor &self, size_t index) -> float { return self.data()[index]; },
|
||||
"When only an index is necessary")
|
||||
.def("__setitem__", [](kp::Tensor &self, size_t index, float value) {
|
||||
self.data()[index] = value; })
|
||||
.def("set_data", [np](kp::Tensor &self, const py::array_t<float> data){
|
||||
const py::array_t<float> flatdata = np.attr("ravel")(data);
|
||||
const py::buffer_info info = flatdata.request();
|
||||
const float* ptr = (float*) info.ptr;
|
||||
self.setData(std::vector<float>(ptr, ptr+flatdata.size()));
|
||||
}, DOC(kp, Tensor, setData))
|
||||
.def("__iter__", [](kp::Tensor &self) {
|
||||
return py::make_iterator(self.data().begin(), self.data().end());
|
||||
}, py::keep_alive<0, 1>(), // Required to keep alive iterator while exists
|
||||
"Iterator to enable looping within data structure as required.")
|
||||
.def("__contains__", [](kp::Tensor &self, float v) {
|
||||
for (size_t i = 0; i < self.data().size(); ++i) {
|
||||
if (v == self.data()[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.def("__reversed__", [](kp::Tensor &self) {
|
||||
size_t size = self.data().size();
|
||||
std::vector<float> reversed(size);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
reversed[size - i - 1] = self.data()[i];
|
||||
// Non-owning container exposing the underlying pointer
|
||||
py::str dummyDataOwner; // Explicitly request data to not be owned by np
|
||||
switch (self.dataType()) {
|
||||
case kp::Tensor::TensorDataTypes::eFloat:
|
||||
return py::array(self.size(), self.data<float>(), dummyDataOwner);
|
||||
case kp::Tensor::TensorDataTypes::eUnsignedInt:
|
||||
return py::array(self.size(), self.data<uint32_t>(), dummyDataOwner);
|
||||
case kp::Tensor::TensorDataTypes::eInt:
|
||||
return py::array(self.size(), self.data<int32_t>(), dummyDataOwner);
|
||||
case kp::Tensor::TensorDataTypes::eDouble:
|
||||
return py::array(self.size(), self.data<double>(), dummyDataOwner);
|
||||
case kp::Tensor::TensorDataTypes::eBool:
|
||||
return py::array(self.size(), self.data<bool>(), dummyDataOwner);
|
||||
default:
|
||||
throw std::runtime_error("Kompute Python data type not supported");
|
||||
}
|
||||
return reversed;
|
||||
})
|
||||
}, DOC(kp, Tensor, data))
|
||||
.def("size", &kp::Tensor::size, DOC(kp, Tensor, size))
|
||||
.def("__len__", &kp::Tensor::size, DOC(kp, Tensor, size))
|
||||
.def("tensor_type", &kp::Tensor::tensorType, DOC(kp, Tensor, tensorType))
|
||||
.def("data_type", &kp::Tensor::dataType, DOC(kp, Tensor, dataType))
|
||||
.def("is_init", &kp::Tensor::isInit, DOC(kp, Tensor, isInit))
|
||||
.def("destroy", &kp::Tensor::destroy, DOC(kp, Tensor, destroy));
|
||||
|
||||
py::class_<kp::Sequence, std::shared_ptr<kp::Sequence>>(m, "Sequence", DOC(kp, Sequence))
|
||||
py::class_<kp::Sequence, std::shared_ptr<kp::Sequence>>(m, "Sequence")
|
||||
.def("record", [](kp::Sequence& self, std::shared_ptr<kp::OpBase> op) { return self.record(op); },
|
||||
DOC(kp, Sequence, record))
|
||||
.def("eval", [](kp::Sequence& self) { return self.eval(); },
|
||||
DOC(kp, Sequence, eval))
|
||||
.def("eval", [](kp::Sequence& self, std::shared_ptr<kp::OpBase> op) { return self.eval(op); },
|
||||
DOC(kp, Sequence, eval))
|
||||
DOC(kp, Sequence, eval_2))
|
||||
.def("eval_async", [](kp::Sequence& self) { return self.eval(); },
|
||||
DOC(kp, Sequence, evalAsync))
|
||||
DOC(kp, Sequence, evalAwait))
|
||||
.def("eval_async", [](kp::Sequence& self, std::shared_ptr<kp::OpBase> op) { return self.evalAsync(op); },
|
||||
DOC(kp, Sequence, evalAsync))
|
||||
.def("eval_await", [](kp::Sequence& self) { return self.evalAwait(); },
|
||||
DOC(kp, Sequence, evalAwait))
|
||||
.def("eval_await", [](kp::Sequence& self, uint32_t wait) { return self.evalAwait(wait); },
|
||||
DOC(kp, Sequence, evalAwait))
|
||||
<<<<<<< HEAD
|
||||
.def("is_recording", &kp::Sequence::isRecording,
|
||||
DOC(kp, Sequence, isRecording))
|
||||
.def("is_running", &kp::Sequence::isRunning,
|
||||
|
|
@ -163,6 +150,17 @@ PYBIND11_MODULE(kp, m) {
|
|||
py::class_<kp::Manager, std::shared_ptr<kp::Manager>>(m, "Manager", DOC(kp, Manager))
|
||||
.def(py::init(), DOC(kp, Manager, Manager))
|
||||
.def(py::init<uint32_t>(), DOC(kp, Manager, Manager_2))
|
||||
=======
|
||||
.def("is_recording", &kp::Sequence::isRecording, DOC(kp, Sequence, isRecording))
|
||||
.def("is_running", &kp::Sequence::isRunning, DOC(kp, Sequence, isRunning))
|
||||
.def("is_init", &kp::Sequence::isInit, DOC(kp, Sequence, isInit))
|
||||
.def("clear", &kp::Sequence::clear, DOC(kp, Sequence, clear))
|
||||
.def("destroy", &kp::Sequence::destroy, DOC(kp, Sequence, destroy));
|
||||
|
||||
py::class_<kp::Manager, std::shared_ptr<kp::Manager>>(m, "Manager")
|
||||
.def(py::init())
|
||||
.def(py::init<uint32_t>())
|
||||
>>>>>>> cc1a6cc (Updated tests and rebased)
|
||||
.def(py::init<uint32_t,const std::vector<uint32_t>&,const std::vector<std::string>&>(),
|
||||
DOC(kp, Manager, Manager_2),
|
||||
py::arg("device") = 0,
|
||||
|
|
@ -173,13 +171,44 @@ PYBIND11_MODULE(kp, m) {
|
|||
.def("tensor", [np](kp::Manager& self,
|
||||
const py::array_t<float> data,
|
||||
kp::Tensor::TensorTypes tensor_type) {
|
||||
const py::array_t<float> flatdata = np.attr("ravel")(data);
|
||||
const py::buffer_info info = flatdata.request();
|
||||
const float* ptr = (float*) info.ptr;
|
||||
return self.tensor(std::vector<float>(ptr, ptr+flatdata.size()), tensor_type);
|
||||
const py::buffer_info info = data.request();
|
||||
return self.tensor(
|
||||
info.ptr,
|
||||
data.size(),
|
||||
sizeof(float),
|
||||
kp::Tensor::TensorDataTypes::eFloat,
|
||||
tensor_type);
|
||||
},
|
||||
DOC(kp, Manager, tensor),
|
||||
py::arg("data"), py::arg("tensor_type") = kp::Tensor::TensorTypes::eDevice)
|
||||
.def("tensor_t", [np](kp::Manager& self,
|
||||
const py::array data,
|
||||
kp::Tensor::TensorTypes tensor_type) {
|
||||
// TODO: confirm if ravel is required as numpy data is always flat
|
||||
//const py::array_t<float> flatdata = np.attr("ravel")(data);
|
||||
//const py::buffer_info info = flatdata.request();
|
||||
const py::buffer_info info = data.request();
|
||||
if (data.dtype() == py::dtype::of<std::float_t>()) {
|
||||
return self.tensor(
|
||||
info.ptr, data.size(), sizeof(float), kp::Tensor::TensorDataTypes::eFloat, tensor_type);
|
||||
} else if (data.dtype() == py::dtype::of<std::uint32_t>()) {
|
||||
return self.tensor(
|
||||
info.ptr, data.size(), sizeof(uint32_t), kp::Tensor::TensorDataTypes::eUnsignedInt, tensor_type);
|
||||
} else if (data.dtype() == py::dtype::of<std::int32_t>()) {
|
||||
return self.tensor(
|
||||
info.ptr, data.size(), sizeof(int32_t), kp::Tensor::TensorDataTypes::eInt, tensor_type);
|
||||
} else if (data.dtype() == py::dtype::of<std::double_t>()) {
|
||||
return self.tensor(
|
||||
info.ptr, data.size(), sizeof(double), kp::Tensor::TensorDataTypes::eDouble, tensor_type);
|
||||
} else if (data.dtype() == py::dtype::of<bool>()) {
|
||||
return self.tensor(
|
||||
info.ptr, data.size(), sizeof(bool), kp::Tensor::TensorDataTypes::eBool, tensor_type);
|
||||
} else {
|
||||
throw std::runtime_error("Kompute Python no valid dtype supported");
|
||||
}
|
||||
},
|
||||
DOC(kp, Manager, tensorT),
|
||||
py::arg("data"), py::arg("tensor_type") = kp::Tensor::TensorTypes::eDevice)
|
||||
.def("algorithm", [](kp::Manager& self,
|
||||
const std::vector<std::shared_ptr<kp::Tensor>>& tensors,
|
||||
const py::bytes& spirv,
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ def test_array_multiplication():
|
|||
mgr = kp.Manager()
|
||||
|
||||
# 2. Create Kompute Tensors to hold data
|
||||
tensor_in_a = mgr.tensor([2, 2, 2])
|
||||
tensor_in_b = mgr.tensor([1, 2, 3])
|
||||
tensor_out = mgr.tensor([0, 0, 0])
|
||||
tensor_in_a = mgr.tensor(np.array([2, 2, 2]))
|
||||
tensor_in_b = mgr.tensor(np.array([1, 2, 3]))
|
||||
tensor_out = mgr.tensor(np.array([0, 0, 0]))
|
||||
|
||||
params = [tensor_in_a, tensor_in_b, tensor_out]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import pyshader as ps
|
||||
import numpy as np
|
||||
import kp
|
||||
|
||||
def test_logistic_regression():
|
||||
|
|
@ -46,21 +47,21 @@ def test_logistic_regression():
|
|||
mgr = kp.Manager(0)
|
||||
|
||||
# First we create input and ouput tensors for shader
|
||||
tensor_x_i = mgr.tensor([0.0, 1.0, 1.0, 1.0, 1.0])
|
||||
tensor_x_j = mgr.tensor([0.0, 0.0, 0.0, 1.0, 1.0])
|
||||
tensor_x_i = mgr.tensor(np.array([0.0, 1.0, 1.0, 1.0, 1.0]))
|
||||
tensor_x_j = mgr.tensor(np.array([0.0, 0.0, 0.0, 1.0, 1.0]))
|
||||
|
||||
tensor_y = mgr.tensor([0.0, 0.0, 0.0, 1.0, 1.0])
|
||||
tensor_y = mgr.tensor(np.array([0.0, 0.0, 0.0, 1.0, 1.0]))
|
||||
|
||||
tensor_w_in = mgr.tensor([0.001, 0.001])
|
||||
tensor_w_out_i = mgr.tensor([0.0, 0.0, 0.0, 0.0, 0.0])
|
||||
tensor_w_out_j = mgr.tensor([0.0, 0.0, 0.0, 0.0, 0.0])
|
||||
tensor_w_in = mgr.tensor(np.array([0.001, 0.001]))
|
||||
tensor_w_out_i = mgr.tensor(np.array([0.0, 0.0, 0.0, 0.0, 0.0]))
|
||||
tensor_w_out_j = mgr.tensor(np.array([0.0, 0.0, 0.0, 0.0, 0.0]))
|
||||
|
||||
tensor_b_in = mgr.tensor([0.0])
|
||||
tensor_b_out = mgr.tensor([0.0, 0.0, 0.0, 0.0, 0.0])
|
||||
tensor_b_in = mgr.tensor(np.array([0.0]))
|
||||
tensor_b_out = mgr.tensor(np.array([0.0, 0.0, 0.0, 0.0, 0.0]))
|
||||
|
||||
tensor_l_out = mgr.tensor([0.0, 0.0, 0.0, 0.0, 0.0])
|
||||
tensor_l_out = mgr.tensor(np.array([0.0, 0.0, 0.0, 0.0, 0.0]))
|
||||
|
||||
tensor_m = mgr.tensor([ tensor_y.size() ])
|
||||
tensor_m = mgr.tensor(np.array([ tensor_y.size() ]))
|
||||
|
||||
# We store them in an array for easier interaction
|
||||
params = [tensor_x_i, tensor_x_j, tensor_y, tensor_w_in, tensor_w_out_i,
|
||||
|
|
@ -91,9 +92,9 @@ def test_logistic_regression():
|
|||
|
||||
# Calculate the parameters based on the respective derivatives calculated
|
||||
for j_iter in range(tensor_b_out.size()):
|
||||
tensor_w_in[0] -= learning_rate * tensor_w_out_i.data()[j_iter]
|
||||
tensor_w_in[1] -= learning_rate * tensor_w_out_j.data()[j_iter]
|
||||
tensor_b_in[0] -= learning_rate * tensor_b_out.data()[j_iter]
|
||||
tensor_w_in.data()[0] -= learning_rate * tensor_w_out_i.data()[j_iter]
|
||||
tensor_w_in.data()[1] -= learning_rate * tensor_w_out_j.data()[j_iter]
|
||||
tensor_b_in.data()[0] -= learning_rate * tensor_b_out.data()[j_iter]
|
||||
|
||||
assert tensor_w_in.data()[0] < 0.01
|
||||
assert tensor_w_in.data()[0] > 0.0
|
||||
|
|
|
|||
2
setup.py
2
setup.py
|
|
@ -57,7 +57,7 @@ class CMakeBuild(build_ext):
|
|||
else:
|
||||
cmake_args += ['-DKOMPUTE_EXTRA_CXX_FLAGS="-fPIC"']
|
||||
cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg]
|
||||
build_args += ['--', '-j2']
|
||||
build_args += ['--', '-j']
|
||||
|
||||
env = os.environ.copy()
|
||||
env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format(env.get('CXXFLAGS', ''),
|
||||
|
|
|
|||
|
|
@ -762,7 +762,7 @@ class Shader
|
|||
* GLSL compiler
|
||||
* @return The compiled SPIR-V binary in unsigned int32 format
|
||||
*/
|
||||
static std::vector<uint32_t> compile_sources(
|
||||
static std::vector<uint32_t> compileSources(
|
||||
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> compile_source(
|
||||
static std::vector<uint32_t> compileSource(
|
||||
const std::string& source,
|
||||
const std::string& entryPoint = "main",
|
||||
std::vector<std::pair<std::string, std::string>> definitions = {},
|
||||
|
|
@ -981,7 +981,7 @@ class Tensor
|
|||
// TODO: move to cpp
|
||||
template <typename T>
|
||||
T* data() {
|
||||
return this->mRawData;
|
||||
return (T*)this->mRawData;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
|
@ -1008,7 +1008,7 @@ class Tensor
|
|||
void* mRawData;
|
||||
|
||||
private:
|
||||
void rawMapData() {
|
||||
void mapRawData() {
|
||||
|
||||
KP_LOG_DEBUG("Kompute Tensor mapping data from host buffer");
|
||||
|
||||
|
|
@ -1025,12 +1025,36 @@ class Tensor
|
|||
}
|
||||
|
||||
vk::DeviceSize bufferSize = this->memorySize();
|
||||
|
||||
// Given we request coherent host memory we don't need to invalidate / flush
|
||||
this->mRawData = this->mDevice->mapMemory(
|
||||
*hostVisibleMemory, 0, bufferSize, vk::MemoryMapFlags());
|
||||
|
||||
vk::MappedMemoryRange mappedMemoryRange(*hostVisibleMemory, 0, bufferSize);
|
||||
}
|
||||
|
||||
void unmapRawData() {
|
||||
|
||||
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();
|
||||
vk::MappedMemoryRange mappedRange(*hostVisibleMemory, 0, bufferSize);
|
||||
this->mDevice->flushMappedMemoryRanges(1, &mappedRange);
|
||||
this->mDevice->unmapMemory(*hostVisibleMemory);
|
||||
}
|
||||
|
||||
// -------------- NEVER OWNED RESOURCES
|
||||
std::shared_ptr<vk::PhysicalDevice> mPhysicalDevice;
|
||||
std::shared_ptr<vk::Device> mDevice;
|
||||
|
|
@ -2011,6 +2035,23 @@ class Manager
|
|||
return this->tensorT<float>(data, tensorType);
|
||||
}
|
||||
|
||||
std::shared_ptr<Tensor> tensor(
|
||||
void* data,
|
||||
uint32_t elementTotalCount,
|
||||
uint32_t elementMemorySize,
|
||||
const Tensor::TensorDataTypes& dataType,
|
||||
Tensor::TensorTypes tensorType = Tensor::TensorTypes::eDevice)
|
||||
{
|
||||
std::shared_ptr<Tensor> tensor{ new kp::Tensor(
|
||||
this->mPhysicalDevice, this->mDevice, data, elementTotalCount, elementMemorySize, dataType, tensorType) };
|
||||
|
||||
if (this->mManageResources) {
|
||||
this->mManagedTensors.push_back(tensor);
|
||||
}
|
||||
|
||||
return tensor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a managed algorithm that will be destroyed by this manager
|
||||
* if it hasn't been destroyed by its reference count going to zero.
|
||||
|
|
|
|||
|
|
@ -98,6 +98,23 @@ class Manager
|
|||
return this->tensorT<float>(data, tensorType);
|
||||
}
|
||||
|
||||
std::shared_ptr<Tensor> tensor(
|
||||
void* data,
|
||||
uint32_t elementTotalCount,
|
||||
uint32_t elementMemorySize,
|
||||
const Tensor::TensorDataTypes& dataType,
|
||||
Tensor::TensorTypes tensorType = Tensor::TensorTypes::eDevice)
|
||||
{
|
||||
std::shared_ptr<Tensor> tensor{ new kp::Tensor(
|
||||
this->mPhysicalDevice, this->mDevice, data, elementTotalCount, elementMemorySize, dataType, tensorType) };
|
||||
|
||||
if (this->mManageResources) {
|
||||
this->mManagedTensors.push_back(tensor);
|
||||
}
|
||||
|
||||
return tensor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a managed algorithm that will be destroyed by this manager
|
||||
* if it hasn't been destroyed by its reference count going to zero.
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ class Tensor
|
|||
// TODO: move to cpp
|
||||
template <typename T>
|
||||
T* data() {
|
||||
return this->mRawData;
|
||||
return (T*)this->mRawData;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
|
|
|||
|
|
@ -78,14 +78,14 @@ TEST(TestDestroy, TestDestroyTensorVector)
|
|||
->record<kp::OpTensorSyncLocal>(algo->getTensors())
|
||||
->eval();
|
||||
|
||||
EXPECT_EQ(tensorA->vector(), std::vector<float>({ 2, 2, 2 }));
|
||||
EXPECT_EQ(tensorB->vector(), std::vector<float>({ 3, 3, 3 }));
|
||||
|
||||
tensorA->destroy();
|
||||
tensorB->destroy();
|
||||
|
||||
EXPECT_FALSE(tensorA->isInit());
|
||||
EXPECT_FALSE(tensorB->isInit());
|
||||
|
||||
EXPECT_EQ(tensorA->vector(), std::vector<float>({ 2, 2, 2 }));
|
||||
EXPECT_EQ(tensorB->vector(), std::vector<float>({ 3, 3, 3 }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -201,40 +201,3 @@ TEST(TestMultipleAlgoExecutions, SingleRecordMultipleEval)
|
|||
EXPECT_EQ(tensorA->vector(), std::vector<float>({ 3, 3, 3 }));
|
||||
}
|
||||
|
||||
TEST(TestMultipleAlgoExecutions, SequenceAlgoDestroyOutsideManagerScope)
|
||||
{
|
||||
std::shared_ptr<kp::TensorT<float>> tensorA = nullptr;
|
||||
|
||||
{
|
||||
std::shared_ptr<kp::Sequence> sq = nullptr;
|
||||
{
|
||||
kp::Manager mgr;
|
||||
|
||||
tensorA = mgr.tensor({ 0, 0, 0 });
|
||||
|
||||
std::string shader(R"(
|
||||
#version 450
|
||||
layout (local_size_x = 1) in;
|
||||
layout(set = 0, binding = 0) buffer a { float pa[]; };
|
||||
void main() {
|
||||
uint index = gl_GlobalInvocationID.x;
|
||||
pa[index] = pa[index] + 1;
|
||||
})");
|
||||
|
||||
std::vector<uint32_t> spirv = kp::Shader::compileSource(shader);
|
||||
|
||||
std::shared_ptr<kp::Algorithm> algorithm =
|
||||
mgr.algorithm({ tensorA }, spirv);
|
||||
|
||||
sq = mgr.sequence();
|
||||
|
||||
sq->record<kp::OpTensorSyncDevice>({ tensorA })->eval();
|
||||
|
||||
sq->record<kp::OpAlgoDispatch>(algorithm)->eval()->eval()->eval();
|
||||
|
||||
sq->record<kp::OpTensorSyncLocal>({ tensorA })->eval();
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ(tensorA->vector(), std::vector<float>({ 3, 3, 3 }));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue