LMMC
Lamina Mathematic core
载入中...
搜索中...
未找到
dense_products.c
浏览该文件的文档.
1
5
6#include <math.h>
7#include <string.h>
8#include "memory_bridge.h"
9#include "internal.h"
10#include "lmmc/config.h"
11#include "lmmc/dense.h"
12#include "lmmc/linear_algebra.h"
13
14static lmmc_status_t lmmc_gemm_storage_check(
15 const lmmc_mat_t* A, const lmmc_mat_t* B, const lmmc_mat_t* C) {
19if (!lmmc_storage_envelope_checked(
20 A->data, A->rows, A->cols, A->stride,
21 sizeof(lmmc_real_t), &a_envelope) ||
22 !lmmc_storage_envelope_checked(
23 B->data, B->rows, B->cols, B->stride,
24 sizeof(lmmc_real_t), &b_envelope) ||
25 !lmmc_storage_envelope_checked(
26 C->data, C->rows, C->cols, C->stride,
27 sizeof(lmmc_real_t), &c_envelope)) {
29}
30if (lmmc_storage_envelopes_overlap(&c_envelope, &a_envelope) ||
31 lmmc_storage_envelopes_overlap(&c_envelope, &b_envelope)) {
33}
34 return LMMC_STATUS_OK;
35}
36
37static lmmc_status_t lmmc_gemv_storage_check(
38 const lmmc_mat_t* A, const lmmc_vec_t* x, const lmmc_vec_t* y) {
42if (!lmmc_storage_envelope_checked(A->data, A->rows, A->cols,
43 A->stride, sizeof(lmmc_real_t),
44 &a_envelope) ||
45 !lmmc_storage_envelope_checked(x->data, 1, x->size, x->size,
46 sizeof(lmmc_real_t), &x_envelope) ||
47 !lmmc_storage_envelope_checked(y->data, 1, y->size, y->size,
48 sizeof(lmmc_real_t), &y_envelope)) {
50}
51if (lmmc_storage_envelopes_overlap(&y_envelope, &a_envelope) ||
52 lmmc_storage_envelopes_overlap(&y_envelope, &x_envelope)) {
54}
55 return LMMC_STATUS_OK;
56}
57
58static void lmmc_gemm_scale(lmmc_mat_t* C, lmmc_real_t beta) {
59 if (beta == 0.0) {
60 for (size_t i = 0; i < C->rows; ++i) {
61 for (size_t j = 0; j < C->cols; ++j) {
62 LMMC_REAL_SET_D(&C->data[i * C->stride + j], 0.0);
63 }
64 }
65 } else if (beta != 1.0) {
66 for (size_t i = 0; i < C->rows; ++i) {
67 for (size_t j = 0; j < C->cols; ++j) {
68 lmmc_real_t scaled;
69 LMMC_REAL_MUL(&scaled, &beta, &C->data[i * C->stride + j]);
70 LMMC_REAL_SET(&C->data[i * C->stride + j], &scaled);
71 }
72 }
73 }
74}
75
76static void lmmc_gemv_scale(lmmc_vec_t* y, lmmc_real_t beta) {
77 if (beta == 0.0) {
78 for (size_t i = 0; i < y->size; ++i) {
79 LMMC_REAL_SET_D(&y->data[i], 0.0);
80 }
81 } else if (beta != 1.0) {
82 for (size_t i = 0; i < y->size; ++i) {
83 lmmc_real_t scaled;
84 LMMC_REAL_MUL(&scaled, &beta, &y->data[i]);
85 LMMC_REAL_SET(&y->data[i], &scaled);
86 }
87 }
88}
89
90static void lmmc_gemm_block(lmmc_real_t alpha, const lmmc_mat_t* A,
91 int transA, const lmmc_mat_t* B, int transB, lmmc_mat_t* C,
92 size_t ii, size_t kk, size_t jj) {
93 size_t K = A->cols;
94 if (transA) {
95 K = A->rows;
96 }
97 size_t i_end = ii + 64;
98 if (i_end > C->rows) {
99 i_end = C->rows;
100 }
101 size_t k_end = kk + 64;
102 if (k_end > K) {
103 k_end = K;
104 }
105 size_t j_end = jj + 64;
106 if (j_end > C->cols) {
107 j_end = C->cols;
108 }
109 for (size_t i = ii; i < i_end; ++i) {
110 for (size_t k = kk; k < k_end; ++k) {
111 lmmc_real_t a_ik;
112 if (transA) {
113 a_ik = A->data[k * A->stride + i];
114 } else {
115 a_ik = A->data[i * A->stride + k];
116 }
117 lmmc_real_t alpha_a_ik;
118 LMMC_REAL_MUL(&alpha_a_ik, &alpha, &a_ik);
119 for (size_t j = jj; j < j_end; ++j) {
120 lmmc_real_t b_kj;
121 if (transB) {
122 b_kj = B->data[j * B->stride + k];
123 } else {
124 b_kj = B->data[k * B->stride + j];
125 }
126 lmmc_real_t tmp_mul;
127 lmmc_real_t tmp_sum;
128 LMMC_REAL_MUL(&tmp_mul, &alpha_a_ik, &b_kj);
129 LMMC_REAL_ADD(&tmp_sum, &C->data[i * C->stride + j], &tmp_mul);
130 LMMC_REAL_SET(&C->data[i * C->stride + j], &tmp_sum);
131 }
132 }
133 }
134}
135
136static void lmmc_gemv_accumulate(lmmc_real_t alpha, const lmmc_mat_t* A,
137 int transA, const lmmc_vec_t* x, lmmc_vec_t* y) {
138 const lmmc_real_t* restrict a_data = A->data;
139 size_t a_stride = A->stride;
140 size_t M = y->size;
141 size_t N = x->size;
143 lmmc_real_t sum; LMMC_REAL_INIT(&sum);
144 lmmc_real_t tmp_mul; LMMC_REAL_INIT(&tmp_mul);
145 lmmc_real_t tmp_sum; LMMC_REAL_INIT(&tmp_sum);
146 lmmc_real_t alpha_sum; LMMC_REAL_INIT(&alpha_sum);
147
148 for (size_t i = 0; i < M; ++i) {
149 LMMC_REAL_SET_D(&sum, 0.0);
150 for (size_t j = 0; j < N; ++j) {
151 lmmc_real_t a_ij;
152 if (transA) {
153 a_ij = a_data[j * a_stride + i];
154 } else {
155 a_ij = a_data[i * a_stride + j];
156 }
157 LMMC_REAL_MUL(&tmp_mul, &a_ij, &x->data[j]);
158 LMMC_REAL_ADD(&tmp_sum, &sum, &tmp_mul);
159 LMMC_REAL_SET(&sum, &tmp_sum);
160 }
162 LMMC_REAL_MUL(&alpha_sum, &alpha, &sum);
163 LMMC_REAL_ADD(&tmp_sum, &y->data[i], &alpha_sum);
164 LMMC_REAL_SET(&y->data[i], &tmp_sum);
165 }
166
167 LMMC_REAL_CLEAR(&sum);
168 LMMC_REAL_CLEAR(&tmp_mul);
169 LMMC_REAL_CLEAR(&tmp_sum);
170 LMMC_REAL_CLEAR(&alpha_sum);
171}
172
173static void lmmc_gemm_accumulate(lmmc_real_t alpha, const lmmc_mat_t* A,
174 int transA, const lmmc_mat_t* B, int transB, lmmc_mat_t* C, size_t K) {
176 for (size_t ii = 0; ii < C->rows; ii += 64) {
177 for (size_t kk = 0; kk < K; kk += 64) {
178 for (size_t jj = 0; jj < C->cols; jj += 64) {
179 lmmc_gemm_block(alpha, A, transA, B, transB, C, ii, kk, jj);
180 }
181 }
182 }
183}
184
186 const lmmc_mat_t* B, int transB, lmmc_real_t beta, lmmc_mat_t* C) {
187 if (!lmmc_mat_descriptor_is_valid(A) ||
188 !lmmc_mat_descriptor_is_valid(B) ||
189 !lmmc_mat_descriptor_is_valid(C)) {
191 }
192
193 size_t M = A->rows;
194 size_t K_A = A->cols;
195 size_t K_B = B->rows;
196 size_t N = B->cols;
197 if (transA) {
198 M = A->cols;
199 K_A = A->rows;
200 }
201 if (transB) {
202 K_B = B->cols;
203 N = B->rows;
204 }
205
206 if (K_A != K_B) {
208 }
209 if (C->rows != M || C->cols != N) {
211 }
212 lmmc_status_t status = lmmc_gemm_storage_check(A, B, C);
213 if (status != LMMC_STATUS_OK) {
214 return status;
215 }
216 lmmc_gemm_scale(C, beta);
217 if (alpha == 0.0) {
218 return LMMC_STATUS_OK;
219 }
220 lmmc_gemm_accumulate(alpha, A, transA, B, transB, C, K_A);
221 return LMMC_STATUS_OK;
222}
223
225 return lmmc_mat_gemm(1.0, a, 0, b, 0, 0.0, c);
226}
227
229 size_t i = 0;
230 if (!lmmc_vec_descriptor_is_valid(a) ||
231 !lmmc_vec_descriptor_is_valid(b) || out_dot == NULL) {
233 }
234 if (a->size != b->size) {
236 }
237
238 lmmc_real_t sum; LMMC_REAL_INIT(&sum);
239 lmmc_real_t tmp_mul; LMMC_REAL_INIT(&tmp_mul);
240 lmmc_real_t tmp_sum; LMMC_REAL_INIT(&tmp_sum);
241 LMMC_REAL_SET_D(&sum, 0.0);
242
243 for (i = 0; i < a->size; ++i) {
244 LMMC_REAL_MUL(&tmp_mul, &a->data[i], &b->data[i]);
245 LMMC_REAL_ADD(&tmp_sum, &sum, &tmp_mul);
246 LMMC_REAL_SET(&sum, &tmp_sum);
247 }
248 LMMC_REAL_SET(out_dot, &sum);
249
250 LMMC_REAL_CLEAR(&sum);
251 LMMC_REAL_CLEAR(&tmp_mul);
252 LMMC_REAL_CLEAR(&tmp_sum);
253 return LMMC_STATUS_OK;
254}
255
257 const lmmc_vec_t* x, lmmc_real_t beta, lmmc_vec_t* y) {
258 if (!lmmc_mat_descriptor_is_valid(A) ||
259 !lmmc_vec_descriptor_is_valid(x) ||
260 !lmmc_vec_descriptor_is_valid(y)) {
262 }
263
264 /* Determine effective dimensions of op(A) */
265 size_t M = transA ? A->cols : A->rows;
266 size_t N = transA ? A->rows : A->cols;
267
268 /* Dimension validation */
269 if (N != x->size || M != y->size) {
271 }
272 lmmc_status_t status = lmmc_gemv_storage_check(A, x, y);
273 if (status != LMMC_STATUS_OK) {
274 return status;
275 }
276 lmmc_gemv_scale(y, beta);
277 if (alpha != 0.0) {
278 lmmc_gemv_accumulate(alpha, A, transA, x, y);
279 }
280 return LMMC_STATUS_OK;
281}
282
284 return lmmc_mat_gemv(1.0, a, 0, x, 0.0, y);
285}
286
288 if (!lmmc_vec_descriptor_is_valid(x) ||
289 !lmmc_vec_descriptor_is_valid(y)) {
291 }
292 if (x->size != y->size) {
294 }
295
296 lmmc_real_t tmp_mul; LMMC_REAL_INIT(&tmp_mul);
297 lmmc_real_t tmp_sum; LMMC_REAL_INIT(&tmp_sum);
298
299 for (size_t i = 0; i < x->size; ++i) {
300 LMMC_REAL_MUL(&tmp_mul, &alpha, &x->data[i]);
301 LMMC_REAL_ADD(&tmp_sum, &y->data[i], &tmp_mul);
302 LMMC_REAL_SET(&y->data[i], &tmp_sum);
303 }
304
305 LMMC_REAL_CLEAR(&tmp_mul);
306 LMMC_REAL_CLEAR(&tmp_sum);
307 return LMMC_STATUS_OK;
308}
LMMC binary real type and arithmetic spelling.
#define LMMC_REAL_CLEAR(x)
释放一个 lmmc_real_t 变量(POD 类型为空操作)。
#define LMMC_REAL_INIT(x)
初始化一个 lmmc_real_t 变量(POD 类型为空操作)。
#define LMMC_REAL_ADD(res, a, b)
计算 *res = *a + *b 。
double lmmc_real_t
Public and internal LMMC real type.
#define LMMC_REAL_SET(dst, src)
将一个 lmmc_real_t 赋值到另一个:*dst = *src 。
#define LMMC_REAL_MUL(res, a, b)
计算 *res = *a * *b 。
#define LMMC_REAL_SET_D(dst, dbl)
将一个 double 字面量赋值到 lmmc_real_t 。
lmmc_status_t lmmc_vec_dot(const lmmc_vec_t *a, const lmmc_vec_t *b, lmmc_real_t *out_dot)
计算两个等长向量的内积: 。
lmmc_status_t lmmc_mat_gemv(lmmc_real_t alpha, const lmmc_mat_t *A, int transA, const lmmc_vec_t *x, lmmc_real_t beta, lmmc_vec_t *y)
通用矩阵-向量乘法(GEMV): 。
lmmc_status_t lmmc_mat_gemm(lmmc_real_t alpha, const lmmc_mat_t *A, int transA, const lmmc_mat_t *B, int transB, lmmc_real_t beta, lmmc_mat_t *C)
通用矩阵-矩阵乘法(GEMM): 。
lmmc_status_t lmmc_vec_axpy(lmmc_real_t alpha, const lmmc_vec_t *x, lmmc_vec_t *y)
向量 AXPY 运算: 。
lmmc_status_t lmmc_mat_vec_mul(const lmmc_mat_t *a, const lmmc_vec_t *x, lmmc_vec_t *y)
计算矩阵与向量的乘积:y = A * x。
lmmc_status_t lmmc_mat_mul(const lmmc_mat_t *a, const lmmc_mat_t *b, lmmc_mat_t *c)
计算矩阵乘积:c = a * b。
lmmc_real_t * data
lmmc_real_t * data
行优先存储的稠密矩阵。
一维稠密向量。
LMMC 内部使用的公共工具(仅源文件可见).
稠密矩阵直接分解接口(LU、Cholesky、QR)。
Private recoverable allocator for persistent LMMC ownership.
lmmc_status_t
LMMC 库统一返回的状态码.
@ LMMC_STATUS_OK
@ LMMC_STATUS_DIMENSION_MISMATCH
@ LMMC_STATUS_INVALID_ARGUMENT