compute-acceleration
GEMM and sum reduction across serial, OpenMP and CUDA
Loading...
Searching...
No Matches
gemm_omp.h
1// Copyright (c) 2025 yanghuafang
2// SPDX-License-Identifier: MIT
3
4#ifndef ACCEL_OMP_GEMM_OMP_H_
5#define ACCEL_OMP_GEMM_OMP_H_
6
7#include "core/gemm_shape.h"
8#include "core/span.h"
9#include "cpu/cpu_gemm.h"
10
11namespace accel {
12
13// Parallel counterparts of the two fastest serial kernels. Both split the M
14// axis, so each thread owns a disjoint set of C rows: the accumulating
15// contract survives with no atomics and no reduction over C, and results stay
16// bit-identical to the serial kernel at any thread count.
17//
18// Only the fastest serial kernels are parallelised. Threading GemmIjk would
19// report a speedup that is mostly the loop reorder it lacks.
20//
21// Contract as in cpu_gemm.h. Validation runs in the serial region, before any
22// thread is spawned, because an exception cannot cross a parallel boundary.
23// Thread count is whatever the runtime supplies; pin it with OpenmpSetThreads.
24
25// GemmIkj with M distributed. Each thread still walks unit-stride B and C, so
26// per-thread vectorisation is unaffected. Expect the curve to bend well before
27// the core count: the kernel streams all of B per row block, so it saturates
28// bandwidth rather than issue width.
29void GemmIkjOmp(Span<const float> a, Span<const float> b, Span<float> c,
30 const GemmShape& shape);
31
32// GemmTiledBColMajor distributed over row *blocks*, so each thread keeps a
33// whole blocked working set resident. Answers whether blocking still pays when
34// threads contend for a shared cache -- the serial answer need not survive.
35// A non-positive tile_size throws std::invalid_argument.
36void GemmTiledBColMajorOmp(Span<const float> a, Span<const float> b_col,
37 Span<float> c, const GemmShape& shape,
38 int tile_size = kDefaultTileSize);
39
40} // namespace accel
41
42#endif // ACCEL_OMP_GEMM_OMP_H_