/
vuron
/
adept
Обзор
Документация
Войти
/
vuron
/
adept
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
with_cpu
tests/matmul_tests.cpp
190 строк
7 KB
kolkir
Add matmul tests
26 мар 2025, 00:49
26 мар 2025, 00:49
27a44dc
Код
Авторство
О чём код?
#include <adept/tensor.hpp> #include <adept/tensor_print.hpp> #include <vector> #include "adept/types.hpp" #include "catch.hpp" using namespace adept; namespace { template <typename T> using Data = std::vector<T>; } TEST_CASE("matmul fail sizes", "[matmul]") { Data<float32_t> dx = {1, 2, 3, 4, 5, 6, 7, 8}; Data<float32_t> dy = {7, 8, 1, 3, 9, 4, 5, 2}; auto x = Tensor::from_blob( dx.data(), {.shape = {2, 4}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); auto y = Tensor::from_blob( dy.data(), {.shape = {2, 4}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); REQUIRE_THROWS(x.matmul(y)); } TEST_CASE("matmul 2x4x2", "[matmul]") { Data<float32_t> dx = {1, 2, 3, 4, 5, 6, 7, 8}; Data<float32_t> dy = {7, 8, 1, 3, 9, 4, 5, 2}; auto x = Tensor::from_blob( dx.data(), {.shape = {2, 4}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); auto y = Tensor::from_blob( dy.data(), {.shape = {4, 2}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); auto z = x.matmul(y); REQUIRE(z.properties().shape.dim(0) == 2); REQUIRE(z.properties().shape.dim(1) == 2); REQUIRE_THAT(z.at<float32_t>({0, 0}), Catch::WithinRel(56.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({0, 1}), Catch::WithinRel(34.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({1, 0}), Catch::WithinRel(144.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({1, 1}), Catch::WithinRel(102.f, 0.001f)); } TEST_CASE("matmul 2x2x4", "[matmul]") { Data<float32_t> dx = {1, 2, 5, 6}; Data<float32_t> dy = {7, 8, 1, 3, 9, 4, 5, 2}; auto x = Tensor::from_blob( dx.data(), {.shape = {2, 2}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); auto y = Tensor::from_blob( dy.data(), {.shape = {2, 4}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); auto z = x.matmul(y); REQUIRE(z.properties().shape.dim(0) == 2); REQUIRE(z.properties().shape.dim(1) == 4); REQUIRE_THAT(z.at<float32_t>({0, 0}), Catch::WithinRel(25.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({0, 1}), Catch::WithinRel(16.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({0, 2}), Catch::WithinRel(11.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({0, 3}), Catch::WithinRel(7.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({1, 0}), Catch::WithinRel(89.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({1, 1}), Catch::WithinRel(64.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({1, 2}), Catch::WithinRel(35.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({1, 3}), Catch::WithinRel(27.f, 0.001f)); } TEST_CASE("matmul 2-2x2", "[matmul]") { // 1x2 * 2x2 = (1x)2 Data<float32_t> dx = {1, 2}; Data<float32_t> dy = {7, 8, 1, 3}; auto x = Tensor::from_blob( dx.data(), {.shape = {2}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); auto y = Tensor::from_blob( dy.data(), {.shape = {2, 2}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); auto z = x.matmul(y); REQUIRE(z.properties().shape.rang() == 1); REQUIRE(z.properties().shape.dim(0) == 2); } TEST_CASE("matmul 2x2-2", "[matmul]") { // 2x2 * 2x1 = 2(x1) Data<float32_t> dx = {1, 2}; Data<float32_t> dy = {7, 8, 1, 3}; auto x = Tensor::from_blob( dx.data(), {.shape = {2}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); auto y = Tensor::from_blob( dy.data(), {.shape = {2, 2}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); auto z = y.matmul(x); REQUIRE(z.properties().shape.rang() == 1); REQUIRE(z.properties().shape.dim(0) == 2); } TEST_CASE("batch matmul fail sizes", "[matmul]") { Data<float32_t> dx = {1, 2, 3, 4, 5, 6, 7, 8}; Data<float32_t> dy = {7, 8, 1, 3, 9, 4, 5, 2, 7, 8, 1, 3, 9, 4, 5, 2}; auto x = Tensor::from_blob( dx.data(), {.shape = {1, 2, 4}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); auto y = Tensor::from_blob( dy.data(), {.shape = {2, 2, 4}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); REQUIRE_THROWS(x.matmul(y)); } TEST_CASE("batch matmul 2x2x4-2x4x2", "[matmul]") { Data<float32_t> dx = {1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}; Data<float32_t> dy = {7, 8, 1, 3, 9, 4, 5, 2, 7, 8, 1, 3, 9, 4, 5, 2}; auto x = Tensor::from_blob( dx.data(), {.shape = {2, 2, 4}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); auto y = Tensor::from_blob( dy.data(), {.shape = {2, 4, 2}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); auto z = x.matmul(y); REQUIRE(z.properties().shape.dim(0) == 2); REQUIRE(z.properties().shape.dim(1) == 2); REQUIRE(z.properties().shape.dim(2) == 2); for (index_t b = 0; b < 2; ++b) { REQUIRE_THAT(z.at<float32_t>({b, 0, 0}), Catch::WithinRel(56.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({b, 0, 1}), Catch::WithinRel(34.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({b, 1, 0}), Catch::WithinRel(144.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({b, 1, 1}), Catch::WithinRel(102.f, 0.001f)); } } TEST_CASE("batch matmul 2x4-2x4x2", "[matmul]") { Data<float32_t> dx = {1, 2, 3, 4, 5, 6, 7, 8}; Data<float32_t> dy = {7, 8, 1, 3, 9, 4, 5, 2, 7, 8, 1, 3, 9, 4, 5, 2}; auto x = Tensor::from_blob( dx.data(), {.shape = {2, 4}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); auto y = Tensor::from_blob( dy.data(), {.shape = {2, 4, 2}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); auto z = x.matmul(y); REQUIRE(z.properties().shape.dim(0) == 2); REQUIRE(z.properties().shape.dim(1) == 2); REQUIRE(z.properties().shape.dim(2) == 2); for (index_t b = 0; b < 2; ++b) { REQUIRE_THAT(z.at<float32_t>({b, 0, 0}), Catch::WithinRel(56.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({b, 0, 1}), Catch::WithinRel(34.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({b, 1, 0}), Catch::WithinRel(144.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({b, 1, 1}), Catch::WithinRel(102.f, 0.001f)); } } TEST_CASE("batch matmul 4-2x4x2", "[matmul]") { // 1x4-2x4x2 Data<float32_t> dx = {1, 2, 3, 4}; Data<float32_t> dy = {7, 8, 1, 3, 9, 4, 5, 2, 7, 8, 1, 3, 9, 4, 5, 2}; auto x = Tensor::from_blob( dx.data(), {.shape = {4}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); auto y = Tensor::from_blob( dy.data(), {.shape = {2, 4, 2}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); auto z = x.matmul(y); REQUIRE(z.properties().shape.rang() == 2); REQUIRE(z.properties().shape.dim(0) == 2); REQUIRE(z.properties().shape.dim(1) == 2); for (index_t b = 0; b < 2; ++b) { REQUIRE_THAT(z.at<float32_t>({b, 0}), Catch::WithinRel(56.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({b, 1}), Catch::WithinRel(34.f, 0.001f)); } } TEST_CASE("batch matmul 2x4x2-2", "[matmul]") { // 1x4-2x4x2 Data<float32_t> dx = {1, 2}; Data<float32_t> dy = {7, 8, 1, 3, 9, 4, 5, 2, 7, 8, 1, 3, 9, 4, 5, 2}; auto x = Tensor::from_blob( dx.data(), {.shape = {2}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); auto y = Tensor::from_blob( dy.data(), {.shape = {2, 4, 2}, .device = device_t::CPU, .dtype = to_dtype<float32_t>()}); auto z = y.matmul(x); REQUIRE(z.properties().shape.rang() == 2); REQUIRE(z.properties().shape.dim(0) == 2); REQUIRE(z.properties().shape.dim(1) == 4); for (index_t b = 0; b < 2; ++b) { REQUIRE_THAT(z.at<float32_t>({b, 0}), Catch::WithinRel(23.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({b, 1}), Catch::WithinRel(7.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({b, 2}), Catch::WithinRel(17.f, 0.001f)); REQUIRE_THAT(z.at<float32_t>({b, 3}), Catch::WithinRel(9.f, 0.001f)); } }