Skip to content

Commit ac4d389

Browse files
committed
test gemm oom
1 parent 544230f commit ac4d389

File tree

1 file changed

+397
-0
lines changed

1 file changed

+397
-0
lines changed

tests/test_gemm_oom.cpp

Lines changed: 397 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,397 @@
1+
// Copyright 2025 Tencent
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
4+
#include "testutil.h"
5+
6+
static int test_gemm_oom(int M, int N, int K, int transA, int transB, int output_transpose, int constantA, int constantB, int output_N1M)
7+
{
8+
ncnn::ParamDict pd;
9+
pd.set(2, transA);
10+
pd.set(3, transB);
11+
pd.set(4, constantA);
12+
pd.set(5, constantB);
13+
pd.set(6, 1);
14+
pd.set(7, M);
15+
pd.set(8, N);
16+
pd.set(9, K);
17+
pd.set(10, -1);
18+
pd.set(11, output_N1M);
19+
pd.set(14, output_transpose);
20+
21+
std::vector<ncnn::Mat> weights;
22+
if (constantA) weights.push_back(transA ? (output_N1M ? ncnn::Mat(M, 1, K) : ncnn::Mat(M, K)) : (output_N1M ? ncnn::Mat(K, 1, M) : ncnn::Mat(K, M)));
23+
if (constantB) weights.push_back(transB ? (output_N1M ? ncnn::Mat(K, 1, N) : ncnn::Mat(K, N)) : (output_N1M ? ncnn::Mat(N, 1, K) : ncnn::Mat(N, K)));
24+
25+
std::vector<ncnn::Mat> a;
26+
if (!constantA) a.push_back(transA ? (output_N1M ? ncnn::Mat(M, 1, K) : ncnn::Mat(M, K)) : (output_N1M ? ncnn::Mat(K, 1, M) : ncnn::Mat(K, M)));
27+
if (!constantB) a.push_back(transB ? (output_N1M ? ncnn::Mat(K, 1, N) : ncnn::Mat(K, N)) : (output_N1M ? ncnn::Mat(N, 1, K) : ncnn::Mat(N, K)));
28+
29+
for (size_t i = 0; i < weights.size(); i++)
30+
{
31+
Randomize(weights[i]);
32+
}
33+
34+
for (size_t i = 0; i < a.size(); i++)
35+
{
36+
Randomize(a[i]);
37+
}
38+
39+
int ret = test_layer_oom("Gemm", pd, weights, a);
40+
if (ret != 0)
41+
{
42+
fprintf(stderr, "test_gemm_oom failed M=%d N=%d K=%d transA=%d transB=%d output_transpose=%d constantA=%d constantB=%d output_N1M=%d\n", M, N, K, transA, transB, output_transpose, constantA, constantB, output_N1M);
43+
}
44+
45+
return ret;
46+
}
47+
48+
static int test_gemm_bias_oom(int M, int N, int K, const ncnn::Mat& C, float alpha, float beta, int transA, int transB, int output_transpose, int constantA, int constantB, int constantC)
49+
{
50+
int broadcast_type_C = 0;
51+
if (C.dims == 1 && C.w == 1)
52+
{
53+
// scalar
54+
broadcast_type_C = 0;
55+
}
56+
if (C.dims == 1 && C.w == M)
57+
{
58+
// M
59+
// auto broadcast from h to w is the ncnn-style convention
60+
broadcast_type_C = 1;
61+
}
62+
if (C.dims == 1 && C.w == N)
63+
{
64+
// N
65+
broadcast_type_C = 4;
66+
}
67+
if (C.dims == 2 && C.w == 1 && C.h == M)
68+
{
69+
// Mx1
70+
broadcast_type_C = 2;
71+
}
72+
if (C.dims == 2 && C.w == N && C.h == M)
73+
{
74+
// MxN
75+
broadcast_type_C = 3;
76+
}
77+
if (C.dims == 2 && C.w == N && C.h == 1)
78+
{
79+
// 1xN
80+
broadcast_type_C = 4;
81+
}
82+
83+
ncnn::ParamDict pd;
84+
pd.set(0, alpha);
85+
pd.set(1, beta);
86+
pd.set(2, transA);
87+
pd.set(3, transB);
88+
pd.set(4, constantA);
89+
pd.set(5, constantB);
90+
pd.set(6, constantC);
91+
pd.set(7, M);
92+
pd.set(8, N);
93+
pd.set(9, K);
94+
pd.set(10, broadcast_type_C);
95+
pd.set(14, output_transpose);
96+
97+
std::vector<ncnn::Mat> weights;
98+
if (constantA) weights.push_back(transA ? ncnn::Mat(M, K) : ncnn::Mat(K, M));
99+
if (constantB) weights.push_back(transB ? ncnn::Mat(K, N) : ncnn::Mat(N, K));
100+
if (constantC) weights.push_back(C);
101+
102+
std::vector<ncnn::Mat> a;
103+
if (!constantA) a.push_back(transA ? ncnn::Mat(M, K) : ncnn::Mat(K, M));
104+
if (!constantB) a.push_back(transB ? ncnn::Mat(K, N) : ncnn::Mat(N, K));
105+
if (!constantC) a.push_back(C);
106+
107+
for (size_t i = 0; i < weights.size(); i++)
108+
{
109+
Randomize(weights[i]);
110+
}
111+
112+
for (size_t i = 0; i < a.size(); i++)
113+
{
114+
Randomize(a[i]);
115+
}
116+
117+
int ret = test_layer_oom("Gemm", pd, weights, a);
118+
if (ret != 0)
119+
{
120+
fprintf(stderr, "test_gemm_bias_oom failed M=%d N=%d K=%d C.dims=%d C=(%d %d %d) alpha=%f beta=%f transA=%d transB=%d output_transpose=%d constantA=%d constantB=%d constantC=%d\n", M, N, K, C.dims, C.w, C.h, C.c, alpha, beta, transA, transB, output_transpose, constantA, constantB, constantC);
121+
}
122+
123+
return ret;
124+
}
125+
126+
static int test_gemm_0(int M, int N, int K)
127+
{
128+
return 0
129+
|| test_gemm_oom(M, N, K, 0, 0, 0, 0, 0, 0)
130+
|| test_gemm_oom(M, N, K, 1, 0, 1, 0, 0, 0)
131+
|| test_gemm_oom(M, N, K, 0, 1, 1, 1, 0, 0)
132+
|| test_gemm_oom(M, N, K, 1, 1, 0, 1, 0, 1)
133+
|| test_gemm_oom(M, N, K, 0, 0, 0, 0, 1, 0)
134+
|| test_gemm_oom(M, N, K, 0, 1, 1, 0, 1, 0)
135+
|| test_gemm_oom(M, N, K, 1, 0, 1, 1, 1, 0)
136+
|| test_gemm_oom(M, N, K, 1, 1, 0, 1, 1, 1);
137+
}
138+
139+
static int test_gemm_1(int M, int N, int K)
140+
{
141+
return 0
142+
|| test_gemm_bias_oom(M, N, K, RandomMat(1), 2.1f, 0.5f, 0, 0, 0, 0, 0, 0)
143+
|| test_gemm_bias_oom(M, N, K, RandomMat(M), 3.1f, 0.6f, 0, 1, 0, 1, 0, 0)
144+
|| test_gemm_bias_oom(M, N, K, RandomMat(1, M), 4.1f, 0.7f, 1, 0, 1, 0, 1, 0)
145+
|| test_gemm_bias_oom(M, N, K, RandomMat(N, M), 5.1f, 0.8f, 1, 1, 1, 1, 1, 0)
146+
|| test_gemm_bias_oom(M, N, K, RandomMat(N, 1), 2.1f, 0.5f, 0, 0, 0, 0, 0, 1)
147+
|| test_gemm_bias_oom(M, N, K, RandomMat(N), 3.1f, 0.6f, 0, 1, 0, 1, 0, 1)
148+
|| test_gemm_bias_oom(M, N, K, RandomMat(M), 3.1f, 0.6f, 0, 1, 0, 0, 1, 1)
149+
|| test_gemm_bias_oom(M, N, K, RandomMat(N, M), 5.1f, 0.8f, 1, 1, 1, 1, 1, 1);
150+
}
151+
152+
#if NCNN_INT8
153+
static int test_gemm_int8_oom(int M, int N, int K, int transA, int transB, int output_elemtype, int output_transpose, int constantA, int constantB, int output_N1M)
154+
{
155+
ncnn::ParamDict pd;
156+
pd.set(2, transA);
157+
pd.set(3, transB);
158+
pd.set(4, constantA);
159+
pd.set(5, constantB);
160+
pd.set(6, 1);
161+
pd.set(7, M);
162+
pd.set(8, N);
163+
pd.set(9, K);
164+
pd.set(10, -1);
165+
pd.set(11, output_N1M);
166+
pd.set(13, output_elemtype);
167+
pd.set(14, output_transpose);
168+
pd.set(18, 2); // int8_scale_term
169+
170+
std::vector<ncnn::Mat> weights;
171+
if (constantA) weights.push_back(transA ? RandomS8Mat(M, K) : RandomS8Mat(K, M));
172+
if (constantB) weights.push_back(transB ? RandomS8Mat(K, N) : RandomS8Mat(N, K));
173+
if (constantA) weights.push_back(RandomMat(M, 10.f, 20.f));
174+
if (constantB) weights.push_back(RandomMat(1, 10.f, 20.f));
175+
176+
std::vector<ncnn::Mat> a;
177+
if (!constantA)
178+
{
179+
a.push_back(transA ? (output_N1M ? ncnn::Mat(M, 1, K) : ncnn::Mat(M, K)) : (output_N1M ? ncnn::Mat(K, 1, M) : ncnn::Mat(K, M)));
180+
}
181+
if (!constantB)
182+
{
183+
a.push_back(transB ? (output_N1M ? ncnn::Mat(K, 1, N) : ncnn::Mat(K, N)) : (output_N1M ? ncnn::Mat(N, 1, K) : ncnn::Mat(N, K)));
184+
}
185+
186+
int ret = test_layer_oom("Gemm", pd, weights, a);
187+
if (ret != 0)
188+
{
189+
fprintf(stderr, "test_gemm_int8_oom failed M=%d N=%d K=%d transA=%d transB=%d output_elemtype=%d output_transpose=%d constantA=%d constantB=%d output_N1M=%d\n", M, N, K, transA, transB, output_elemtype, output_transpose, constantA, constantB, output_N1M);
190+
}
191+
192+
return ret;
193+
}
194+
195+
static int test_gemm_int8_bias_oom(int M, int N, int K, const ncnn::Mat& C, float alpha, float beta, int transA, int transB, int output_elemtype, int output_transpose, int constantA, int constantB, int constantC)
196+
{
197+
int broadcast_type_C = 0;
198+
if (C.dims == 1 && C.w == 1)
199+
{
200+
// scalar
201+
broadcast_type_C = 0;
202+
}
203+
if (C.dims == 1 && C.w == M)
204+
{
205+
// M
206+
// auto broadcast from h to w is the ncnn-style convention
207+
broadcast_type_C = 1;
208+
}
209+
if (C.dims == 1 && C.w == N)
210+
{
211+
// N
212+
broadcast_type_C = 4;
213+
}
214+
if (C.dims == 2 && C.w == 1 && C.h == M)
215+
{
216+
// Mx1
217+
broadcast_type_C = 2;
218+
}
219+
if (C.dims == 2 && C.w == N && C.h == M)
220+
{
221+
// MxN
222+
broadcast_type_C = 3;
223+
}
224+
if (C.dims == 2 && C.w == N && C.h == 1)
225+
{
226+
// 1xN
227+
broadcast_type_C = 4;
228+
}
229+
230+
ncnn::ParamDict pd;
231+
pd.set(0, alpha);
232+
pd.set(1, beta);
233+
pd.set(2, transA);
234+
pd.set(3, transB);
235+
pd.set(4, constantA);
236+
pd.set(5, constantB);
237+
pd.set(6, constantC);
238+
pd.set(7, M);
239+
pd.set(8, N);
240+
pd.set(9, K);
241+
pd.set(10, broadcast_type_C);
242+
pd.set(13, output_elemtype);
243+
pd.set(14, output_transpose);
244+
pd.set(18, 2); // int8_scale_term
245+
246+
std::vector<ncnn::Mat> weights;
247+
if (constantA) weights.push_back(transA ? RandomS8Mat(M, K) : RandomS8Mat(K, M));
248+
if (constantB) weights.push_back(transB ? RandomS8Mat(K, N) : RandomS8Mat(N, K));
249+
if (constantC) weights.push_back(C);
250+
if (constantA) weights.push_back(RandomMat(M, 10.f, 20.f));
251+
if (constantB) weights.push_back(RandomMat(1, 10.f, 20.f));
252+
253+
std::vector<ncnn::Mat> a;
254+
if (!constantA)
255+
{
256+
a.push_back(transA ? ncnn::Mat(M, K) : ncnn::Mat(K, M));
257+
}
258+
if (!constantB)
259+
{
260+
a.push_back(transB ? ncnn::Mat(K, N) : ncnn::Mat(N, K));
261+
}
262+
if (!constantC) a.push_back(C);
263+
264+
int ret = test_layer_oom("Gemm", pd, weights, a);
265+
if (ret != 0)
266+
{
267+
fprintf(stderr, "test_gemm_int8_bias_oom failed M=%d N=%d K=%d C.dims=%d C=(%d %d %d) alpha=%f beta=%f transA=%d transB=%d output_elemtype=%d output_transpose=%d constantA=%d constantB=%d constantC=%d\n", M, N, K, C.dims, C.w, C.h, C.c, alpha, beta, transA, transB, output_elemtype, output_transpose, constantA, constantB, constantC);
268+
}
269+
270+
return ret;
271+
}
272+
273+
static int test_gemm_int8_fp16s_oom(int M, int N, int K, int transA, int transB, int output_elemtype, int output_transpose, int constantA, int constantB, int output_N1M)
274+
{
275+
ncnn::ParamDict pd;
276+
pd.set(2, transA);
277+
pd.set(3, transB);
278+
pd.set(4, constantA);
279+
pd.set(5, constantB);
280+
pd.set(6, 1);
281+
pd.set(7, M);
282+
pd.set(8, N);
283+
pd.set(9, K);
284+
pd.set(10, -1);
285+
pd.set(11, output_N1M);
286+
pd.set(13, output_elemtype);
287+
pd.set(14, output_transpose);
288+
pd.set(18, 2); // int8_scale_term
289+
290+
std::vector<ncnn::Mat> weights;
291+
if (constantA) weights.push_back(transA ? RandomS8Mat(M, K) : RandomS8Mat(K, M));
292+
if (constantB) weights.push_back(transB ? RandomS8Mat(K, N) : RandomS8Mat(N, K));
293+
if (constantA) weights.push_back(RandomMat(M, 10.f, 20.f));
294+
if (constantB) weights.push_back(RandomMat(1, 10.f, 20.f));
295+
296+
std::vector<ncnn::Mat> a;
297+
if (!constantA)
298+
{
299+
a.push_back(transA ? (output_N1M ? ncnn::Mat(M, 1, K) : ncnn::Mat(M, K)) : (output_N1M ? ncnn::Mat(K, 1, M) : ncnn::Mat(K, M)));
300+
}
301+
if (!constantB)
302+
{
303+
a.push_back(transB ? (output_N1M ? ncnn::Mat(K, 1, N) : ncnn::Mat(K, N)) : (output_N1M ? ncnn::Mat(N, 1, K) : ncnn::Mat(N, K)));
304+
}
305+
306+
ncnn::Option opt;
307+
opt.num_threads = 1;
308+
opt.use_packing_layout = true;
309+
opt.use_fp16_packed = false;
310+
opt.use_fp16_storage = true;
311+
opt.use_fp16_arithmetic = false;
312+
opt.use_bf16_storage = false;
313+
314+
float epsilon = 0.001;
315+
316+
int ret = test_layer_oom_opt("Gemm", pd, weights, opt, a, 1, epsilon);
317+
if (ret != 0)
318+
{
319+
fprintf(stderr, "test_gemm_int8_fp16s_oom failed M=%d N=%d K=%d transA=%d transB=%d output_elemtype=%d output_transpose=%d constantA=%d constantB=%d output_N1M=%d\n", M, N, K, transA, transB, output_elemtype, output_transpose, constantA, constantB, output_N1M);
320+
return ret;
321+
}
322+
323+
return 0;
324+
}
325+
326+
static int test_gemm_2(int M, int N, int K)
327+
{
328+
return 0
329+
|| test_gemm_int8_oom(M, N, K, 0, 0, 0, 0, 0, 0, 0)
330+
|| test_gemm_int8_oom(M, N, K, 1, 0, 0, 1, 0, 0, 0)
331+
|| test_gemm_int8_oom(M, N, K, 0, 1, 1, 1, 1, 0, 0)
332+
|| test_gemm_int8_oom(M, N, K, 1, 1, 0, 0, 1, 0, 1)
333+
|| test_gemm_int8_oom(M, N, K, 0, 0, 2, 0, 0, 1, 0)
334+
|| test_gemm_int8_oom(M, N, K, 0, 1, 0, 1, 0, 1, 0)
335+
|| test_gemm_int8_oom(M, N, K, 1, 0, 0, 1, 1, 1, 0)
336+
|| test_gemm_int8_oom(M, N, K, 1, 1, 3, 0, 1, 1, 1);
337+
}
338+
339+
static int test_gemm_3(int M, int N, int K)
340+
{
341+
return 0
342+
|| test_gemm_int8_bias_oom(M, N, K, RandomMat(1), 2.1f, 0.5f, 0, 0, 0, 0, 0, 0, 0)
343+
|| test_gemm_int8_bias_oom(M, N, K, RandomMat(M), 3.1f, 0.6f, 0, 1, 0, 0, 1, 0, 0)
344+
|| test_gemm_int8_bias_oom(M, N, K, RandomMat(1, M), 4.1f, 0.7f, 1, 0, 1, 1, 0, 1, 0)
345+
|| test_gemm_int8_bias_oom(M, N, K, RandomMat(N, M), 5.1f, 0.8f, 1, 1, 0, 1, 1, 1, 0)
346+
|| test_gemm_int8_bias_oom(M, N, K, RandomMat(N, 1), 2.1f, 0.5f, 0, 0, 3, 0, 0, 0, 1)
347+
|| test_gemm_int8_bias_oom(M, N, K, RandomMat(N), 3.1f, 0.6f, 0, 1, 0, 0, 1, 0, 1)
348+
|| test_gemm_int8_bias_oom(M, N, K, RandomMat(M), 3.1f, 0.6f, 0, 1, 0, 0, 0, 1, 1)
349+
|| test_gemm_int8_bias_oom(M, N, K, RandomMat(N, M), 5.1f, 0.8f, 1, 1, 2, 1, 1, 1, 1);
350+
}
351+
352+
static int test_gemm_4(int M, int N, int K)
353+
{
354+
return 0
355+
|| test_gemm_int8_fp16s_oom(M, N, K, 0, 0, 0, 0, 0, 0, 0)
356+
|| test_gemm_int8_fp16s_oom(M, N, K, 1, 0, 0, 1, 0, 0, 0)
357+
|| test_gemm_int8_fp16s_oom(M, N, K, 0, 1, 3, 1, 1, 0, 0)
358+
|| test_gemm_int8_fp16s_oom(M, N, K, 1, 1, 0, 0, 1, 0, 1)
359+
|| test_gemm_int8_fp16s_oom(M, N, K, 0, 0, 2, 0, 0, 1, 0)
360+
|| test_gemm_int8_fp16s_oom(M, N, K, 0, 1, 0, 1, 0, 1, 0)
361+
|| test_gemm_int8_fp16s_oom(M, N, K, 1, 0, 0, 1, 1, 1, 0)
362+
|| test_gemm_int8_fp16s_oom(M, N, K, 1, 1, 1, 0, 1, 1, 1);
363+
}
364+
#endif // NCNN_INT8
365+
366+
int main()
367+
{
368+
SRAND(7767517);
369+
370+
int mnk[][3] = {
371+
{11, 12, 13},
372+
{1, 2, 3},
373+
{4, 1, 6},
374+
{9, 8, 7}
375+
};
376+
377+
int mnk_count = sizeof(mnk) / sizeof(int) / 3;
378+
379+
for (int i = 0; i < mnk_count; i++)
380+
{
381+
int M = mnk[i][0];
382+
int N = mnk[i][1];
383+
int K = mnk[i][2];
384+
385+
int ret = test_gemm_0(M, N, K) || test_gemm_1(M, N, K);
386+
if (ret != 0)
387+
return ret;
388+
389+
#if NCNN_INT8
390+
int ret2 = test_gemm_0(M, N, K) || test_gemm_1(M, N, K);
391+
if (ret2 != 0)
392+
return ret2;
393+
#endif
394+
}
395+
396+
return 0;
397+
}

0 commit comments

Comments
 (0)