| 4 | |
| 5 | template<class AType, class BType, class CType, class AccumType> |
| 6 | void reference_cpu_gemm(GemmParams<AType, BType, CType, AccumType> params) { |
| 7 | /// pointers in params are guaranteed to be in cpu memory |
| 8 | int M = params.M; |
| 9 | int N = params.N; |
| 10 | int K = params.K; |
| 11 | const AType* hA = params.A; |
| 12 | const BType* hB = params.B; |
| 13 | CType* golden = params.C; |
| 14 | #pragma omp parallel for |
| 15 | for (int i = 0; i < M; i += 64) |
| 16 | { |
| 17 | #pragma omp parallel for |
| 18 | for (int j = 0; j < N; j += 64) |
| 19 | { |
| 20 | AccumType accum[64 * 64] = {0}; |
| 21 | for (int k = 0; k < K; k += 32) |
| 22 | { |
| 23 | for (int kk = 0; kk < 32; ++kk) |
| 24 | { |
| 25 | if (k + kk >= K) break; |
| 26 | for (int jj = 0; jj < 64; ++jj) |
| 27 | { |
| 28 | for (int ii = 0; ii < 64; ++ii) |
| 29 | { |
| 30 | accum[ii * 64 + jj] += ((AccumType)hA[(i + ii) % M * K + k + kk] * (AccumType)hB[(j + jj) % N * K + k + kk]); |
| 31 | } |
| 32 | } |
| 33 | } |
| 34 | } |
| 35 | for (int ii = 0; ii < 64; ++ii) |
| 36 | { |
| 37 | for (int jj = 0; jj < 64; ++jj) |
| 38 | { |
| 39 | if (i + ii < M && j + jj < N) { |
| 40 | golden[(i + ii) * N + j + jj] = (CType)(accum[ii * 64 + jj] * params.alpha + params.beta); |
| 41 | } |
| 42 | } |
| 43 | } |
| 44 | } |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | |
| 49 | template<class AType, class BType, class CType, class AccumType, |
nothing calls this directly
no outgoing calls
no test coverage detected