aboutsummaryrefslogtreecommitdiff
path: root/experiments/matmul.cpp
diff options
context:
space:
mode:
authory-jan137 <yousefjan24000@gmail.com>2026-05-16 12:10:05 +0300
committery-jan137 <yousefjan24000@gmail.com>2026-05-16 12:10:05 +0300
commit750f276a1403c5defd58b06f13c703b5e3d59245 (patch)
tree5218b52ca98f6df3fa4e202ff999b81f35c4e28b /experiments/matmul.cpp
parent92220ea5a483d6ece73bb6472af0773bc4106d73 (diff)
Finish TODOs
Diffstat (limited to 'experiments/matmul.cpp')
-rw-r--r--experiments/matmul.cpp130
1 files changed, 0 insertions, 130 deletions
diff --git a/experiments/matmul.cpp b/experiments/matmul.cpp
deleted file mode 100644
index a33b501..0000000
--- a/experiments/matmul.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-import linalgebra;
-import std;
-
-#if !defined(LINEAR_ALGEBRA_FORCE_SCALAR_MATMUL) && \
- defined(__ARM_NEON) && defined(__aarch64__) && \
- defined(__ARM_FEATURE_FP64_VECTOR_ARITHMETIC)
-# define MATMUL_BACKEND "NEON"
-#else
-# define MATMUL_BACKEND "scalar"
-#endif
-
-using linalgebra::Matrix;
-using Clock = std::chrono::high_resolution_clock;
-using Seconds = std::chrono::duration<double>;
-
-
-Matrix naive_matmul(const Matrix& lhs, const Matrix& rhs) {
- if (lhs.cols() != rhs.rows()) {
- throw linalgebra::DimensionMismatchError(
- "naive_matmul: lhs.cols() != rhs.rows()");
- }
- const std::size_t m = lhs.rows();
- const std::size_t n = rhs.cols();
- const std::size_t k = lhs.cols();
-
- Matrix result(m, n, 0.0);
-
- const double* A = lhs.data();
- const double* B = rhs.data();
- double* C = result.data();
-
- for (std::size_t i = 0; i < m; ++i)
- for (std::size_t j = 0; j < n; ++j)
- for (std::size_t p = 0; p < k; ++p)
- C[i * n + j] += A[i * k + p] * B[p * n + j];
-
- return result;
-}
-
-Matrix make_matrix(std::size_t n) {
- Matrix M(n, n);
- const double inv = 1.0 / static_cast<double>(n + 1);
- for (std::size_t i = 0; i < n; ++i)
- for (std::size_t j = 0; j < n; ++j)
- M(i, j) = static_cast<double>(i + j + 1) * inv;
- return M;
-}
-
-template <typename Fn>
-double min_time_s(Fn fn, int trials) {
- double best = 1e30;
- for (int t = 0; t < trials; ++t) {
- const auto t0 = Clock::now();
- fn();
- const auto t1 = Clock::now();
- const double elapsed = Seconds(t1 - t0).count();
- if (elapsed < best) best = elapsed;
- }
- return best;
-}
-
-double flops(std::size_t n) {
- const double nd = static_cast<double>(n);
- return 2.0 * nd * nd * nd;
-}
-
-
-int main() {
- const std::vector<std::size_t> sizes = {
- 8, 16, 32, 64, 128, 256, 512
- };
-
- constexpr std::size_t small_threshold = 128;
- constexpr int trials_small = 9;
- constexpr int trials_large = 3;
-
- std::cout << std::string(72, '*') << "\n";
- std::cout << " Matmul benchmark: naive (ijk) vs SIMD (" MATMUL_BACKEND
- ") + transpose\n";
- std::cout << " C = A * B, A and B both n×n\n";
- std::cout << std::string(72, '*') << "\n\n";
-
- std::cout << std::left
- << std::setw(6) << "n"
- << std::setw(14) << "naive ms"
- << std::setw(14) << "naive GFLOP/s"
- << std::setw(14) << "SIMD ms"
- << std::setw(14) << "SIMD GFLOP/s"
- << std::setw(10) << "speedup"
- << "\n";
- std::cout << std::string(72, '-') << "\n";
-
- for (const std::size_t n : sizes) {
- const Matrix A = make_matrix(n);
- const Matrix B = make_matrix(n);
-
- const int trials = (n <= small_threshold) ? trials_small : trials_large;
-
- volatile double sink_naive = naive_matmul(A, B)(0, 0);
- volatile double sink_simd = (A * B)(0, 0);
- (void)sink_naive;
- (void)sink_simd;
-
- const double t_naive = min_time_s([&] { (void)naive_matmul(A, B); }, trials);
- const double t_simd = min_time_s([&] { (void)(A * B); }, trials);
-
- const double fp = flops(n);
- const double gf_naive = fp / t_naive / 1e9;
- const double gf_simd = fp / t_simd / 1e9;
- const double speedup = t_naive / t_simd;
-
- std::cout << std::left << std::setw(6) << n
- << std::fixed << std::setprecision(3)
- << std::setw(14) << t_naive * 1e3
- << std::setprecision(2)
- << std::setw(14) << gf_naive
- << std::setprecision(3)
- << std::setw(14) << t_simd * 1e3
- << std::setprecision(2)
- << std::setw(14) << gf_simd
- << std::setprecision(2) << std::setw(10) << speedup
- << "x\n";
- }
-
- std::cout << "\n(each cell = minimum over "
- << trials_small << " trials for n<=" << small_threshold
- << ", " << trials_large << " trials for larger n)\n";
-
- return 0;
-}