From 00a49531b46aaa732cd77632a277714f18e18ed8 Mon Sep 17 00:00:00 2001 From: fushenshen Date: Fri, 16 Dec 2022 16:28:05 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E7=AC=AC=E4=BA=8C=E6=AC=A1=E8=AF=BE?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 4 +- include/data/tensor.hpp | 81 +++++++++++++++++++ main.cpp | 12 +-- source/data/tensor.cpp | 168 ++++++++++++++++++++++++++++++++++++++++ test/CMakeLists.txt | 3 +- test/test_first.cpp | 52 ++++++------- test/test_second.cpp | 3 - test/test_tensor.cpp | 69 +++++++++++++++++ 8 files changed, 352 insertions(+), 40 deletions(-) create mode 100644 include/data/tensor.hpp create mode 100644 source/data/tensor.cpp delete mode 100644 test/test_second.cpp create mode 100644 test/test_tensor.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9789f21..521a9ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,12 +4,14 @@ project(kuiper_course) set(CMAKE_CXX_STANDARD 17) find_package(glog REQUIRED) +include_directories(./include) set(link_lib glog pthread gtest) set(link_math_lib armadillo blas lapack) -add_executable(kuiper_course main.cpp) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) +add_executable(kuiper_course main.cpp) + target_include_directories(kuiper_course PUBLIC /usr/include/armadillo_bits) target_include_directories(kuiper_course PUBLIC ${GTEST_INCLUDE_DIRS}) target_link_libraries(kuiper_course ${link_lib} ${link_math_lib}) diff --git a/include/data/tensor.hpp b/include/data/tensor.hpp new file mode 100644 index 0000000..7973144 --- /dev/null +++ b/include/data/tensor.hpp @@ -0,0 +1,81 @@ +// +// Created by fss on 22-12-16. +// + +#ifndef KUIPER_COURSE_INCLUDE_TENSOR_HPP_ +#define KUIPER_COURSE_INCLUDE_TENSOR_HPP_ +#include +#include +#include + +namespace kuiper_infer { + +template +class Tensor { + +}; + +template<> +class Tensor { + // 待实现 +}; + +template<> +class Tensor { + public: + explicit Tensor() = default; + + explicit Tensor(uint32_t channels, uint32_t rows, uint32_t cols); + + Tensor(const Tensor &tensor); + + Tensor &operator=(const Tensor &tensor); + + uint32_t rows() const; + + uint32_t cols() const; + + uint32_t channels() const; + + uint32_t size() const; + + void set_data(const arma::fcube &data); + + bool empty() const; + + float index(uint32_t offset) const; + + std::vector shapes() const; + + arma::fcube &data(); + + const arma::fcube &data() const; + + arma::fmat &at(uint32_t channel); + + const arma::fmat &at(uint32_t channel) const; + + float at(uint32_t channel, uint32_t row, uint32_t col) const; + + float &at(uint32_t channel, uint32_t row, uint32_t col); + + void Padding(const std::vector &pads, float padding_value); + + void Fill(float value); + + void Fill(const std::vector &values); + + void Ones(); + + void Rand(); + + void Show(); + + void Flatten(); + + private: + std::vector raw_shapes_; + arma::fcube data_; +}; +} +#endif //KUIPER_COURSE_INCLUDE_TENSOR_HPP_ diff --git a/main.cpp b/main.cpp index 81cd4bd..95894d6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,12 +1,6 @@ -#include -#include -int main() { - arma::fmat in_1(32, 32, arma::fill::ones); - arma::fmat in_2(32, 32, arma::fill::ones); +#include - arma::fmat out = in_1 + in_2; - std::cout << "rows " << out.n_rows << "\n"; - std::cout << "cols " << out.n_cols << "\n"; - std::cout << "value " << out.at(0) << "\n"; +int main() { + LOG(INFO) << "Kuiper Infer Course"; return 0; } diff --git a/source/data/tensor.cpp b/source/data/tensor.cpp new file mode 100644 index 0000000..b61dfb9 --- /dev/null +++ b/source/data/tensor.cpp @@ -0,0 +1,168 @@ +// +// Created by fss on 22-12-16. +// +#include "data/tensor.hpp" +#include +#include + +namespace kuiper_infer { + +Tensor::Tensor(uint32_t channels, uint32_t rows, uint32_t cols) { + data_ = arma::fcube(rows, cols, channels); +} + +Tensor::Tensor(const Tensor &tensor) { + this->data_ = tensor.data_; + this->raw_shapes_ = tensor.raw_shapes_; +} + +Tensor &Tensor::operator=(const Tensor &tensor) { + if (this != &tensor) { + this->data_ = tensor.data_; + this->raw_shapes_ = tensor.raw_shapes_; + } + return *this; +} + +uint32_t Tensor::rows() const { + CHECK(!this->data_.empty()); + return this->data_.n_rows; +} + +uint32_t Tensor::cols() const { + CHECK(!this->data_.empty()); + return this->data_.n_cols; +} + +uint32_t Tensor::channels() const { + CHECK(!this->data_.empty()); + return this->data_.n_slices; +} + +uint32_t Tensor::size() const { + CHECK(!this->data_.empty()); + return this->data_.size(); +} + +void Tensor::set_data(const arma::fcube &data) { + CHECK(data.n_rows == this->data_.n_rows) << data.n_rows << " != " << this->data_.n_rows; + CHECK(data.n_cols == this->data_.n_cols) << data.n_cols << " != " << this->data_.n_cols; + CHECK(data.n_slices == this->data_.n_slices) << data.n_slices << " != " << this->data_.n_slices; + this->data_ = data; +} + +bool Tensor::empty() const { + return this->data_.empty(); +} + +float Tensor::index(uint32_t offset) const { + CHECK(offset < this->data_.size()); + return this->data_.at(offset); +} + +std::vector Tensor::shapes() const { + CHECK(!this->data_.empty()); + return {this->channels(), this->rows(), this->cols()}; +} + +arma::fcube &Tensor::data() { + return this->data_; +} + +const arma::fcube &Tensor::data() const { + return this->data_; +} + +arma::fmat &Tensor::at(uint32_t channel) { + CHECK_LT(channel, this->channels()); + return this->data_.slice(channel); +} + +const arma::fmat &Tensor::at(uint32_t channel) const { + CHECK_LT(channel, this->channels()); + return this->data_.slice(channel); +} + +float Tensor::at(uint32_t channel, uint32_t row, uint32_t col) const { + CHECK_LT(row, this->rows()); + CHECK_LT(col, this->cols()); + CHECK_LT(channel, this->channels()); + return this->data_.at(row, col, channel); +} + +float &Tensor::at(uint32_t channel, uint32_t row, uint32_t col) { + CHECK_LT(row, this->rows()); + CHECK_LT(col, this->cols()); + CHECK_LT(channel, this->channels()); + return this->data_.at(row, col, channel); +} + +void Tensor::Padding(const std::vector &pads, float padding_value) { + CHECK(!this->data_.empty()); + CHECK_EQ(pads.size(), 4); + uint32_t pad_rows1 = pads.at(0); // up + uint32_t pad_rows2 = pads.at(1); // bottom + uint32_t pad_cols1 = pads.at(2); // left + uint32_t pad_cols2 = pads.at(3); // right + +} + +void Tensor::Fill(float value) { + CHECK(!this->data_.empty()); + this->data_.fill(value); +} + +void Tensor::Fill(const std::vector &values) { + CHECK(!this->data_.empty()); + const uint32_t total_elems = this->data_.size(); + CHECK_EQ(values.size(), total_elems); + + const uint32_t rows = this->rows(); + const uint32_t cols = this->cols(); + const uint32_t planes = rows * cols; + const uint32_t channels = this->data_.n_slices; + +} + +void Tensor::Show() { + for (uint32_t i = 0; i < this->channels(); ++i) { + LOG(INFO) << "Channel: " << i; + LOG(INFO) << "\n" << this->data_.slice(i); + } +} + +void Tensor::Flatten() { + CHECK(!this->data_.empty()); + const uint32_t size = this->data_.size(); + arma::fcube linear_cube(size, 1, 1); + + uint32_t channel = this->channels(); + uint32_t rows = this->rows(); + uint32_t cols = this->cols(); + uint32_t index = 0; + + for (uint32_t c = 0; c < channel; ++c) { + const arma::fmat &matrix = this->data_.slice(c); + + for (uint32_t r = 0; r < rows; ++r) { + for (uint32_t c_ = 0; c_ < cols; ++c_) { + linear_cube.at(index, 0, 0) = matrix.at(r, c_); + index += 1; + } + } + } + CHECK_EQ(index, size); + this->data_ = linear_cube; + this->raw_shapes_ = std::vector{size}; +} + +void Tensor::Rand() { + CHECK(!this->data_.empty()); + this->data_.randn(); +} + +void Tensor::Ones() { + CHECK(!this->data_.empty()); + this->data_.fill(1.); +} +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7520a23..9d511f0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -4,7 +4,8 @@ aux_source_directory(../test DIR_TEST) set(link_lib glog gtest pthread ) set(link_math_lib armadillo blas lapack) -add_executable(test_kuiper_course ${DIR_TEST}) +aux_source_directory(../source/data DIR_DATA) +add_executable(test_kuiper_course ${DIR_TEST} ${DIR_DATA}) link_directories(/usr/local/lib/) target_link_libraries(test_kuiper_course ${link_lib} ${link_math_lib}) diff --git a/test/test_first.cpp b/test/test_first.cpp index 79db762..c72b0c4 100644 --- a/test/test_first.cpp +++ b/test/test_first.cpp @@ -14,29 +14,29 @@ TEST(test_first, demo1) { ASSERT_EQ(in_1.size(), 32 * 32); } -TEST(test_first, linear) { - arma::fmat A = "1,2,3;" - "4,5,6;" - "7,8,9;"; - - arma::fmat X = "1,1,1;" - "1,1,1;" - "1,1,1;"; - - arma::fmat bias = "1,1,1;" - "1,1,1;" - "1,1,1;"; - - arma::fmat output(3, 3); - //todo 在此处插入代码,完成output = AxX + bias的运算 - // output = ? - - const uint32_t cols = 3; - for (uint32_t c = 0; c < cols; ++c) { - float *col_ptr = output.colptr(c); - ASSERT_EQ(*(col_ptr + 0), 7); - ASSERT_EQ(*(col_ptr + 1), 16); - ASSERT_EQ(*(col_ptr + 2), 25); - } - LOG(INFO) << "\n" <<"Result Passed!"; -} +//TEST(test_first, linear) { +// arma::fmat A = "1,2,3;" +// "4,5,6;" +// "7,8,9;"; +// +// arma::fmat X = "1,1,1;" +// "1,1,1;" +// "1,1,1;"; +// +// arma::fmat bias = "1,1,1;" +// "1,1,1;" +// "1,1,1;"; +// +// arma::fmat output(3, 3); +// //todo 在此处插入代码,完成output = AxX + bias的运算 +// // output = ? +// +// const uint32_t cols = 3; +// for (uint32_t c = 0; c < cols; ++c) { +// float *col_ptr = output.colptr(c); +// ASSERT_EQ(*(col_ptr + 0), 7); +// ASSERT_EQ(*(col_ptr + 1), 16); +// ASSERT_EQ(*(col_ptr + 2), 25); +// } +// LOG(INFO) << "\n" <<"Result Passed!"; +//} diff --git a/test/test_second.cpp b/test/test_second.cpp deleted file mode 100644 index a345c16..0000000 --- a/test/test_second.cpp +++ /dev/null @@ -1,3 +0,0 @@ -// -// Created by fss on 22-12-14. -// diff --git a/test/test_tensor.cpp b/test/test_tensor.cpp new file mode 100644 index 0000000..070f77d --- /dev/null +++ b/test/test_tensor.cpp @@ -0,0 +1,69 @@ +// +// Created by fss on 22-12-14. +// +#include "data/tensor.hpp" +#include +#include +#include +#include "data/tensor.hpp" + +TEST(test_tensor, create) { + using namespace kuiper_infer; + Tensor tensor(3, 32, 32); + ASSERT_EQ(tensor.channels(), 3); + ASSERT_EQ(tensor.rows(), 32); + ASSERT_EQ(tensor.cols(), 32); +} + +TEST(test_tensor, fill) { + using namespace kuiper_infer; + Tensor tensor(3, 3, 3); + ASSERT_EQ(tensor.channels(), 3); + ASSERT_EQ(tensor.rows(), 3); + ASSERT_EQ(tensor.cols(), 3); + + std::vector values; + for (int i = 0; i < 27; ++i) { + values.push_back((float) i); + } + tensor.Fill(values); + LOG(INFO) << tensor.data(); + + int index = 0; + for (int c = 0; c < tensor.channels(); ++c) { + for (int c_ = 0; c_ < tensor.cols(); ++c_) { + for (int r = 0; r < tensor.rows(); ++r) { + ASSERT_EQ(values.at(index), tensor.at(c, c_, r)); + index += 1; + } + } + } + LOG(INFO) << "Test1 passed!"; +} + +TEST(test_tensor, padding1) { + using namespace kuiper_infer; + Tensor tensor(3, 3, 3); + ASSERT_EQ(tensor.channels(), 3); + ASSERT_EQ(tensor.rows(), 3); + ASSERT_EQ(tensor.cols(), 3); + + tensor.Fill(1.f); // 填充为1 + tensor.Padding({1, 1, 1, 1}, 0); // 边缘填充为0 + ASSERT_EQ(tensor.rows(), 5); + ASSERT_EQ(tensor.cols(), 5); + + int index = 0; + // 检查一下边缘被填充的行、列是否都是0 + for (int c = 0; c < tensor.channels(); ++c) { + for (int c_ = 0; c_ < tensor.cols(); ++c_) { + for (int r = 0; r < tensor.rows(); ++r) { + if (c_ == 0 || r == 0) { + ASSERT_EQ(tensor.at(c, c_, r), 0); + } + index += 1; + } + } + } + LOG(INFO) << "Test2 passed!"; +} \ No newline at end of file From 3c3c4abb6d2e11fccfd8465393923567a439f653 Mon Sep 17 00:00:00 2001 From: fushenshen Date: Fri, 16 Dec 2022 16:38:34 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E7=AC=AC=E4=BA=8C=E6=AC=A1=E8=AF=BE?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/data/tensor.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/data/tensor.cpp b/source/data/tensor.cpp index b61dfb9..da29302 100644 --- a/source/data/tensor.cpp +++ b/source/data/tensor.cpp @@ -105,6 +105,8 @@ void Tensor::Padding(const std::vector &pads, float padding_val uint32_t pad_cols1 = pads.at(2); // left uint32_t pad_cols2 = pads.at(3); // right + //todo 请把代码补充在这里1 + } void Tensor::Fill(float value) { @@ -122,6 +124,7 @@ void Tensor::Fill(const std::vector &values) { const uint32_t planes = rows * cols; const uint32_t channels = this->data_.n_slices; + //todo 请把代码补充在这里2 } void Tensor::Show() { From 683a65197a735de74e8db045e33da381018d6e31 Mon Sep 17 00:00:00 2001 From: Zachary Xue Date: Thu, 22 Dec 2022 19:09:32 +0900 Subject: [PATCH 3/5] remove redundant "data/tensor.hpp" --- test/test_tensor.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/test_tensor.cpp b/test/test_tensor.cpp index 070f77d..16d8a7e 100644 --- a/test/test_tensor.cpp +++ b/test/test_tensor.cpp @@ -1,7 +1,6 @@ // // Created by fss on 22-12-14. // -#include "data/tensor.hpp" #include #include #include @@ -66,4 +65,4 @@ TEST(test_tensor, padding1) { } } LOG(INFO) << "Test2 passed!"; -} \ No newline at end of file +} From 6c24d04098eff11be14c783eb858889d96c1ec36 Mon Sep 17 00:00:00 2001 From: fushenshen Date: Sat, 14 Jan 2023 19:09:56 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E7=AC=AC=E4=BA=8C=E6=AC=A1=E8=AF=BE?= =?UTF-8?q?=E7=A8=8B=E4=B8=AD=E7=9A=84=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/test_tensor.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_tensor.cpp b/test/test_tensor.cpp index 070f77d..74998e0 100644 --- a/test/test_tensor.cpp +++ b/test/test_tensor.cpp @@ -31,9 +31,9 @@ TEST(test_tensor, fill) { int index = 0; for (int c = 0; c < tensor.channels(); ++c) { - for (int c_ = 0; c_ < tensor.cols(); ++c_) { - for (int r = 0; r < tensor.rows(); ++r) { - ASSERT_EQ(values.at(index), tensor.at(c, c_, r)); + for (int r = 0; r < tensor.rows(); ++r) { + for (int c_ = 0; c_ < tensor.cols(); ++c_) { + ASSERT_EQ(values.at(index), tensor.at(c, r, c_)); index += 1; } } From a05f66dbd425ed3307b5a4f1102148dd130381e3 Mon Sep 17 00:00:00 2001 From: fushenshen Date: Sat, 14 Jan 2023 23:31:20 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E7=AC=AC=E4=BA=8C=E6=AC=A1=E8=AF=BE?= =?UTF-8?q?=E7=A8=8B=E4=B8=AD=E7=9A=84=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/test_tensor.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_tensor.cpp b/test/test_tensor.cpp index a601557..8a39ebb 100644 --- a/test/test_tensor.cpp +++ b/test/test_tensor.cpp @@ -55,10 +55,10 @@ TEST(test_tensor, padding1) { int index = 0; // 检查一下边缘被填充的行、列是否都是0 for (int c = 0; c < tensor.channels(); ++c) { - for (int c_ = 0; c_ < tensor.cols(); ++c_) { - for (int r = 0; r < tensor.rows(); ++r) { + for (int r = 0; r < tensor.rows(); ++r) { + for (int c_ = 0; c_ < tensor.cols(); ++c_) { if (c_ == 0 || r == 0) { - ASSERT_EQ(tensor.at(c, c_, r), 0); + ASSERT_EQ(tensor.at(c, r, c_), 0); } index += 1; }