]>
git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/isa-l/erasure_code/gf_vect_dot_prod_test.c
1 /**********************************************************************
2 Copyright(c) 2011-2015 Intel Corporation All rights reserved.
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in
11 the documentation and/or other materials provided with the
13 * Neither the name of Intel Corporation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 **********************************************************************/
32 #include <string.h> // for memset, memcmp
33 #include "erasure_code.h"
36 #ifndef FUNCTION_UNDER_TEST
37 # define FUNCTION_UNDER_TEST gf_vect_dot_prod
40 # define TEST_MIN_SIZE 32
44 #define xstr(s) str(s)
47 #define TEST_SIZE (TEST_LEN/2)
50 # define TEST_SOURCES 16
56 #define MMAX TEST_SOURCES
57 #define KMAX TEST_SOURCES
59 #ifdef EC_ALIGNED_ADDR
60 // Define power of 2 range to check ptr, len alignment
61 # define PTR_ALIGN_CHK_B 0
62 # define LEN_ALIGN_CHK_B 0 // 0 for aligned only
64 // Define power of 2 range to check ptr, len alignment
65 # define PTR_ALIGN_CHK_B 32
66 # define LEN_ALIGN_CHK_B 32 // 0 for aligned only
69 typedef unsigned char u8
;
71 void dump(unsigned char *buf
, int len
)
74 for (i
= 0; i
< len
;) {
75 printf(" %2x", 0xff & buf
[i
++]);
82 void dump_matrix(unsigned char **s
, int k
, int m
)
85 for (i
= 0; i
< k
; i
++) {
86 for (j
= 0; j
< m
; j
++) {
87 printf(" %2x", s
[i
][j
]);
94 void dump_u8xu8(unsigned char *s
, int k
, int m
)
97 for (i
= 0; i
< k
; i
++) {
98 for (j
= 0; j
< m
; j
++) {
99 printf(" %2x", 0xff & s
[j
+ (i
* m
)]);
106 int main(int argc
, char *argv
[])
108 int i
, j
, rtest
, srcs
, m
, k
, nerrs
, r
, err
;
110 u8 g
[TEST_SOURCES
], g_tbls
[TEST_SOURCES
* 32], src_in_err
[TEST_SOURCES
];
111 u8
*dest
, *dest_ref
, *temp_buff
, *buffs
[TEST_SOURCES
];
112 u8 a
[MMAX
* KMAX
], b
[MMAX
* KMAX
], d
[MMAX
* KMAX
];
113 u8 src_err_list
[TEST_SOURCES
], *recov
[TEST_SOURCES
];
116 unsigned char *efence_buffs
[TEST_SOURCES
];
118 u8
*ubuffs
[TEST_SOURCES
];
121 printf(xstr(FUNCTION_UNDER_TEST
) ": %dx%d ", TEST_SOURCES
, TEST_LEN
);
123 // Allocate the arrays
124 for (i
= 0; i
< TEST_SOURCES
; i
++) {
125 if (posix_memalign(&buf
, 64, TEST_LEN
)) {
126 printf("alloc error: Fail");
132 if (posix_memalign(&buf
, 64, TEST_LEN
)) {
133 printf("alloc error: Fail");
138 if (posix_memalign(&buf
, 64, TEST_LEN
)) {
139 printf("alloc error: Fail");
144 if (posix_memalign(&buf
, 64, TEST_LEN
)) {
145 printf("alloc error: Fail");
151 for (i
= 0; i
< TEST_SOURCES
; i
++)
152 memset(buffs
[i
], 0, TEST_LEN
);
154 memset(dest
, 0, TEST_LEN
);
155 memset(temp_buff
, 0, TEST_LEN
);
156 memset(dest_ref
, 0, TEST_LEN
);
157 memset(g
, 0, TEST_SOURCES
);
159 for (i
= 0; i
< TEST_SOURCES
; i
++)
160 gf_vect_mul_init(g
[i
], &g_tbls
[i
* 32]);
162 gf_vect_dot_prod_base(TEST_LEN
, TEST_SOURCES
, &g_tbls
[0], buffs
, dest_ref
);
164 FUNCTION_UNDER_TEST(TEST_LEN
, TEST_SOURCES
, g_tbls
, buffs
, dest
);
166 if (0 != memcmp(dest_ref
, dest
, TEST_LEN
)) {
167 printf("Fail zero " xstr(FUNCTION_UNDER_TEST
) " \n");
168 dump_matrix(buffs
, 5, TEST_SOURCES
);
169 printf("dprod_base:");
178 for (rtest
= 0; rtest
< RANDOMS
; rtest
++) {
179 for (i
= 0; i
< TEST_SOURCES
; i
++)
180 for (j
= 0; j
< TEST_LEN
; j
++)
181 buffs
[i
][j
] = rand();
183 for (i
= 0; i
< TEST_SOURCES
; i
++)
186 for (i
= 0; i
< TEST_SOURCES
; i
++)
187 gf_vect_mul_init(g
[i
], &g_tbls
[i
* 32]);
189 gf_vect_dot_prod_base(TEST_LEN
, TEST_SOURCES
, &g_tbls
[0], buffs
, dest_ref
);
190 FUNCTION_UNDER_TEST(TEST_LEN
, TEST_SOURCES
, g_tbls
, buffs
, dest
);
192 if (0 != memcmp(dest_ref
, dest
, TEST_LEN
)) {
193 printf("Fail rand " xstr(FUNCTION_UNDER_TEST
) " 1\n");
194 dump_matrix(buffs
, 5, TEST_SOURCES
);
195 printf("dprod_base:");
205 // Rand data test with varied parameters
206 for (rtest
= 0; rtest
< RANDOMS
; rtest
++) {
207 for (srcs
= TEST_SOURCES
; srcs
> 0; srcs
--) {
208 for (i
= 0; i
< srcs
; i
++)
209 for (j
= 0; j
< TEST_LEN
; j
++)
210 buffs
[i
][j
] = rand();
212 for (i
= 0; i
< srcs
; i
++)
215 for (i
= 0; i
< srcs
; i
++)
216 gf_vect_mul_init(g
[i
], &g_tbls
[i
* 32]);
218 gf_vect_dot_prod_base(TEST_LEN
, srcs
, &g_tbls
[0], buffs
, dest_ref
);
219 FUNCTION_UNDER_TEST(TEST_LEN
, srcs
, g_tbls
, buffs
, dest
);
221 if (0 != memcmp(dest_ref
, dest
, TEST_LEN
)) {
222 printf("Fail rand " xstr(FUNCTION_UNDER_TEST
) " test 2\n");
223 dump_matrix(buffs
, 5, srcs
);
224 printf("dprod_base:");
235 // Test erasure code using gf_vect_dot_prod
240 if (m
> MMAX
|| k
> KMAX
)
243 gf_gen_rs_matrix(a
, m
, k
);
246 for (i
= 0; i
< k
; i
++)
247 for (j
= 0; j
< TEST_LEN
; j
++)
248 buffs
[i
][j
] = rand();
251 for (i
= k
; i
< m
; i
++) {
252 for (j
= 0; j
< k
; j
++)
253 gf_vect_mul_init(a
[k
* i
+ j
], &g_tbls
[j
* 32]);
255 FUNCTION_UNDER_TEST(TEST_LEN
, k
, g_tbls
, buffs
, buffs
[i
]);
257 gf_vect_dot_prod_base(TEST_LEN
, k
, &g_tbls
[0], buffs
, buffs
[i
]);
261 // Random buffers in erasure
262 memset(src_in_err
, 0, TEST_SOURCES
);
263 for (i
= 0, nerrs
= 0; i
< k
&& nerrs
< m
- k
; i
++) {
267 src_err_list
[nerrs
++] = i
;
270 // construct b by removing error rows
271 for (i
= 0, r
= 0; i
< k
; i
++, r
++) {
272 while (src_in_err
[r
]) {
276 for (j
= 0; j
< k
; j
++)
277 b
[k
* i
+ j
] = a
[k
* r
+ j
];
280 if (gf_invert_matrix((u8
*) b
, (u8
*) d
, k
) < 0)
281 printf("BAD MATRIX\n");
283 for (i
= 0, r
= 0; i
< k
; i
++, r
++) {
284 while (src_in_err
[r
]) {
292 for (i
= 0; i
< nerrs
; i
++) {
293 for (j
= 0; j
< k
; j
++)
294 gf_vect_mul_init(d
[k
* src_err_list
[i
] + j
], &g_tbls
[j
* 32]);
296 FUNCTION_UNDER_TEST(TEST_LEN
, k
, g_tbls
, recov
, temp_buff
);
298 gf_vect_dot_prod_base(TEST_LEN
, k
, &g_tbls
[0], recov
, temp_buff
);
301 if (0 != memcmp(temp_buff
, buffs
[src_err_list
[i
]], TEST_LEN
)) {
302 printf("Fail error recovery (%d, %d, %d)\n", m
, k
, nerrs
);
303 printf("recov %d:", src_err_list
[i
]);
306 dump(buffs
[src_err_list
[i
]], 25);
311 // Do more random tests
313 for (rtest
= 0; rtest
< RANDOMS
; rtest
++) {
314 while ((m
= (rand() % MMAX
)) < 2) ;
315 while ((k
= (rand() % KMAX
)) >= m
|| k
< 1) ;
317 if (m
> MMAX
|| k
> KMAX
)
320 gf_gen_rs_matrix(a
, m
, k
);
323 for (i
= 0; i
< k
; i
++)
324 for (j
= 0; j
< TEST_LEN
; j
++)
325 buffs
[i
][j
] = rand();
328 for (i
= k
; i
< m
; i
++) {
329 for (j
= 0; j
< k
; j
++)
330 gf_vect_mul_init(a
[k
* i
+ j
], &g_tbls
[j
* 32]);
332 FUNCTION_UNDER_TEST(TEST_LEN
, k
, g_tbls
, buffs
, buffs
[i
]);
334 gf_vect_dot_prod_base(TEST_LEN
, k
, &g_tbls
[0], buffs
, buffs
[i
]);
339 memset(src_in_err
, 0, TEST_SOURCES
);
340 for (i
= 0, nerrs
= 0; i
< k
&& nerrs
< m
- k
; i
++) {
344 src_err_list
[nerrs
++] = i
;
346 if (nerrs
== 0) { // should have at least one error
347 while ((err
= (rand() % KMAX
)) >= k
) ;
348 src_err_list
[nerrs
++] = err
;
351 // construct b by removing error rows
352 for (i
= 0, r
= 0; i
< k
; i
++, r
++) {
353 while (src_in_err
[r
]) {
357 for (j
= 0; j
< k
; j
++)
358 b
[k
* i
+ j
] = a
[k
* r
+ j
];
361 if (gf_invert_matrix((u8
*) b
, (u8
*) d
, k
) < 0)
362 printf("BAD MATRIX\n");
364 for (i
= 0, r
= 0; i
< k
; i
++, r
++) {
365 while (src_in_err
[r
]) {
373 for (i
= 0; i
< nerrs
; i
++) {
374 for (j
= 0; j
< k
; j
++)
375 gf_vect_mul_init(d
[k
* src_err_list
[i
] + j
], &g_tbls
[j
* 32]);
377 FUNCTION_UNDER_TEST(TEST_LEN
, k
, g_tbls
, recov
, temp_buff
);
379 gf_vect_dot_prod_base(TEST_LEN
, k
, &g_tbls
[0], recov
, temp_buff
);
381 if (0 != memcmp(temp_buff
, buffs
[src_err_list
[i
]], TEST_LEN
)) {
382 printf("Fail error recovery (%d, %d, %d) - ", m
, k
, nerrs
);
383 printf(" - erase list = ");
384 for (i
= 0; i
< nerrs
; i
++)
385 printf(" %d", src_err_list
[i
]);
387 dump_u8xu8((u8
*) a
, m
, k
);
389 dump_u8xu8((u8
*) d
, k
, k
);
390 printf("orig data:\n");
391 dump_matrix(buffs
, m
, 25);
393 dump(buffs
[src_err_list
[i
]], 25);
394 printf("recov %d:", src_err_list
[i
]);
402 // Run tests at end of buffer for Electric Fence
403 align
= (LEN_ALIGN_CHK_B
!= 0) ? 1 : 16;
404 for (size
= TEST_MIN_SIZE
; size
<= TEST_SIZE
; size
+= align
) {
405 for (i
= 0; i
< TEST_SOURCES
; i
++)
406 for (j
= 0; j
< TEST_LEN
; j
++)
407 buffs
[i
][j
] = rand();
409 for (i
= 0; i
< TEST_SOURCES
; i
++) // Line up TEST_SIZE from end
410 efence_buffs
[i
] = buffs
[i
] + TEST_LEN
- size
;
412 for (i
= 0; i
< TEST_SOURCES
; i
++)
415 for (i
= 0; i
< TEST_SOURCES
; i
++)
416 gf_vect_mul_init(g
[i
], &g_tbls
[i
* 32]);
418 gf_vect_dot_prod_base(size
, TEST_SOURCES
, &g_tbls
[0], efence_buffs
, dest_ref
);
419 FUNCTION_UNDER_TEST(size
, TEST_SOURCES
, g_tbls
, efence_buffs
, dest
);
421 if (0 != memcmp(dest_ref
, dest
, size
)) {
422 printf("Fail rand " xstr(FUNCTION_UNDER_TEST
) " test 3\n");
423 dump_matrix(efence_buffs
, 5, TEST_SOURCES
);
424 printf("dprod_base:");
425 dump(dest_ref
, align
);
434 // Test rand ptr alignment if available
436 for (rtest
= 0; rtest
< RANDOMS
; rtest
++) {
437 size
= (TEST_LEN
- PTR_ALIGN_CHK_B
) & ~(TEST_MIN_SIZE
- 1);
438 srcs
= rand() % TEST_SOURCES
;
442 offset
= (PTR_ALIGN_CHK_B
!= 0) ? 1 : PTR_ALIGN_CHK_B
;
443 // Add random offsets
444 for (i
= 0; i
< srcs
; i
++)
445 ubuffs
[i
] = buffs
[i
] + (rand() & (PTR_ALIGN_CHK_B
- offset
));
447 udest_ptr
= dest
+ (rand() & (PTR_ALIGN_CHK_B
- offset
));
449 memset(dest
, 0, TEST_LEN
); // zero pad to check write-over
451 for (i
= 0; i
< srcs
; i
++)
452 for (j
= 0; j
< size
; j
++)
453 ubuffs
[i
][j
] = rand();
455 for (i
= 0; i
< srcs
; i
++)
458 for (i
= 0; i
< srcs
; i
++)
459 gf_vect_mul_init(g
[i
], &g_tbls
[i
* 32]);
461 gf_vect_dot_prod_base(size
, srcs
, &g_tbls
[0], ubuffs
, dest_ref
);
463 FUNCTION_UNDER_TEST(size
, srcs
, g_tbls
, ubuffs
, udest_ptr
);
465 if (memcmp(dest_ref
, udest_ptr
, size
)) {
466 printf("Fail rand " xstr(FUNCTION_UNDER_TEST
) " ualign srcs=%d\n",
468 dump_matrix(ubuffs
, 5, TEST_SOURCES
);
469 printf("dprod_base:");
475 // Confirm that padding around dests is unchanged
476 memset(dest_ref
, 0, PTR_ALIGN_CHK_B
); // Make reference zero buff
477 offset
= udest_ptr
- dest
;
479 if (memcmp(dest
, dest_ref
, offset
)) {
480 printf("Fail rand ualign pad start\n");
483 if (memcmp(dest
+ offset
+ size
, dest_ref
, PTR_ALIGN_CHK_B
- offset
)) {
484 printf("Fail rand ualign pad end\n");
491 // Test all size alignment
492 align
= (LEN_ALIGN_CHK_B
!= 0) ? 1 : 16;
494 for (size
= TEST_LEN
; size
>= TEST_MIN_SIZE
; size
-= align
) {
497 for (i
= 0; i
< srcs
; i
++)
498 for (j
= 0; j
< size
; j
++)
499 buffs
[i
][j
] = rand();
501 for (i
= 0; i
< srcs
; i
++)
504 for (i
= 0; i
< srcs
; i
++)
505 gf_vect_mul_init(g
[i
], &g_tbls
[i
* 32]);
507 gf_vect_dot_prod_base(size
, srcs
, &g_tbls
[0], buffs
, dest_ref
);
509 FUNCTION_UNDER_TEST(size
, srcs
, g_tbls
, buffs
, dest
);
511 if (memcmp(dest_ref
, dest
, size
)) {
512 printf("Fail rand " xstr(FUNCTION_UNDER_TEST
) " ualign len=%d\n",
514 dump_matrix(buffs
, 5, TEST_SOURCES
);
515 printf("dprod_base:");
523 printf("done all: Pass\n");