erasure_code_update_perf.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /**********************************************************************
  2. Copyright(c) 2011-2015 Intel Corporation All rights reserved.
  3. Redistribution and use in source and binary forms, with or without
  4. modification, are permitted provided that the following conditions
  5. are met:
  6. * Redistributions of source code must retain the above copyright
  7. notice, this list of conditions and the following disclaimer.
  8. * Redistributions in binary form must reproduce the above copyright
  9. notice, this list of conditions and the following disclaimer in
  10. the documentation and/or other materials provided with the
  11. distribution.
  12. * Neither the name of Intel Corporation nor the names of its
  13. contributors may be used to endorse or promote products derived
  14. from this software without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  16. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  17. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  18. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  19. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  20. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  21. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  22. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  23. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  25. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. **********************************************************************/
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h> // for memset, memcmp
  30. #include "erasure_code.h"
  31. #include "test.h"
  32. //By default, test multibinary version
  33. #ifndef FUNCTION_UNDER_TEST
  34. # define FUNCTION_UNDER_TEST ec_encode_data_update
  35. # define REF_FUNCTION ec_encode_data
  36. #endif
  37. //By default, test EC(8+4)
  38. #if (!defined(VECT))
  39. # define VECT 4
  40. #endif
  41. #define str(s) #s
  42. #define xstr(s) str(s)
  43. #ifndef GT_L3_CACHE
  44. # define GT_L3_CACHE 32*1024*1024 /* some number > last level cache */
  45. #endif
  46. #if !defined(COLD_TEST) && !defined(TEST_CUSTOM)
  47. // Cached test, loop many times over small dataset
  48. # define TEST_SOURCES 32
  49. # define TEST_LEN(m) ((128*1024 / m) & ~(64-1))
  50. # define TEST_TYPE_STR "_warm"
  51. #elif defined (COLD_TEST)
  52. // Uncached test. Pull from large mem base.
  53. # define TEST_SOURCES 32
  54. # define TEST_LEN(m) ((GT_L3_CACHE / m) & ~(64-1))
  55. # define TEST_TYPE_STR "_cold"
  56. #elif defined (TEST_CUSTOM)
  57. # define TEST_TYPE_STR "_cus"
  58. #endif
  59. #ifndef TEST_SEED
  60. # define TEST_SEED 0x1234
  61. #endif
  62. #define MMAX TEST_SOURCES
  63. #define KMAX TEST_SOURCES
  64. typedef unsigned char u8;
  65. void usage(const char *app_name)
  66. {
  67. fprintf(stderr,
  68. "Usage: %s [options]\n"
  69. " -h Help\n"
  70. " -k <val> Number of source buffers\n"
  71. " -p <val> Number of parity buffers\n"
  72. " -e <val> Number of simulated buffers with errors (cannot be higher than p or k)\n",
  73. app_name);
  74. }
  75. void dump(unsigned char *buf, int len)
  76. {
  77. int i;
  78. for (i = 0; i < len;) {
  79. printf(" %2x", 0xff & buf[i++]);
  80. if (i % 32 == 0)
  81. printf("\n");
  82. }
  83. printf("\n");
  84. }
  85. void encode_update_test_ref(int m, int k, u8 * g_tbls, u8 ** buffs, u8 * a)
  86. {
  87. ec_init_tables(k, m - k, &a[k * k], g_tbls);
  88. REF_FUNCTION(TEST_LEN(m), k, m - k, g_tbls, buffs, &buffs[k]);
  89. }
  90. void encode_update_test(int m, int k, u8 * g_tbls, u8 ** perf_update_buffs, u8 * a)
  91. {
  92. int i;
  93. // Make parity vects
  94. ec_init_tables(k, m - k, &a[k * k], g_tbls);
  95. for (i = 0; i < k; i++) {
  96. FUNCTION_UNDER_TEST(TEST_LEN(m), k, m - k, i, g_tbls,
  97. perf_update_buffs[i], &perf_update_buffs[k]);
  98. }
  99. }
  100. int decode_test(int m, int k, u8 ** update_buffs, u8 ** recov, u8 * a, u8 * src_in_err,
  101. u8 * src_err_list, int nerrs, u8 * g_tbls, u8 ** perf_update_buffs)
  102. {
  103. int i, j, r;
  104. u8 b[MMAX * KMAX], c[MMAX * KMAX], d[MMAX * KMAX];
  105. // Construct b by removing error rows
  106. for (i = 0, r = 0; i < k; i++, r++) {
  107. while (src_in_err[r])
  108. r++;
  109. recov[i] = update_buffs[r];
  110. for (j = 0; j < k; j++)
  111. b[k * i + j] = a[k * r + j];
  112. }
  113. if (gf_invert_matrix(b, d, k) < 0) {
  114. printf("BAD MATRIX\n");
  115. return -1;
  116. }
  117. for (i = 0; i < nerrs; i++)
  118. for (j = 0; j < k; j++)
  119. c[k * i + j] = d[k * src_err_list[i] + j];
  120. // Recover data
  121. ec_init_tables(k, nerrs, c, g_tbls);
  122. for (i = 0; i < k; i++) {
  123. FUNCTION_UNDER_TEST(TEST_LEN(m), k, nerrs, i, g_tbls, recov[i],
  124. perf_update_buffs);
  125. }
  126. return 0;
  127. }
  128. int main(int argc, char *argv[])
  129. {
  130. int i, j, check, m, k, p, nerrs, ret = -1;
  131. void *buf;
  132. u8 *temp_buffs[TEST_SOURCES] = { NULL };
  133. u8 *buffs[TEST_SOURCES] = { NULL };
  134. u8 *update_buffs[TEST_SOURCES] = { NULL };
  135. u8 *perf_update_buffs[TEST_SOURCES] = { NULL };
  136. u8 a[MMAX * KMAX];
  137. u8 g_tbls[KMAX * TEST_SOURCES * 32], src_in_err[TEST_SOURCES];
  138. u8 src_err_list[TEST_SOURCES], *recov[TEST_SOURCES];
  139. struct perf start;
  140. /* Set default parameters */
  141. k = 10;
  142. p = VECT;
  143. nerrs = VECT;
  144. /* Parse arguments */
  145. for (i = 1; i < argc; i++) {
  146. if (strcmp(argv[i], "-k") == 0) {
  147. k = atoi(argv[++i]);
  148. } else if (strcmp(argv[i], "-p") == 0) {
  149. p = atoi(argv[++i]);
  150. } else if (strcmp(argv[i], "-e") == 0) {
  151. nerrs = atoi(argv[++i]);
  152. } else if (strcmp(argv[i], "-h") == 0) {
  153. usage(argv[0]);
  154. return 0;
  155. } else {
  156. usage(argv[0]);
  157. return -1;
  158. }
  159. }
  160. if (nerrs > k) {
  161. printf
  162. ("Number of errors (%d) cannot be higher than number of data buffers (%d)\n",
  163. nerrs, k);
  164. return -1;
  165. }
  166. if (k <= 0) {
  167. printf("Number of source buffers (%d) must be > 0\n", k);
  168. return -1;
  169. }
  170. if (p <= 0) {
  171. printf("Number of parity buffers (%d) must be > 0\n", p);
  172. return -1;
  173. }
  174. if (nerrs > p) {
  175. printf
  176. ("Number of errors (%d) cannot be higher than number of parity buffers (%d)\n",
  177. nerrs, p);
  178. return -1;
  179. }
  180. if (nerrs <= 0) {
  181. printf("Number of errors (%d) must be > 0\n", nerrs);
  182. return -1;
  183. }
  184. m = k + p;
  185. if (m > MMAX) {
  186. printf("Number of total buffers (data and parity) cannot be higher than %d\n",
  187. MMAX);
  188. return -1;
  189. }
  190. u8 *err_list = malloc((size_t)nerrs);
  191. if (err_list == NULL) {
  192. printf("Error allocating list of array of error indices\n");
  193. return -1;
  194. }
  195. srand(TEST_SEED);
  196. for (i = 0; i < nerrs;) {
  197. u8 next_err = rand() % k;
  198. for (j = 0; j < i; j++)
  199. if (next_err == err_list[j])
  200. break;
  201. if (j != i)
  202. continue;
  203. err_list[i++] = next_err;
  204. }
  205. printf("Testing with %u data buffers and %u parity buffers (num errors = %u, in [ ", k,
  206. p, nerrs);
  207. for (i = 0; i < nerrs; i++)
  208. printf("%d ", err_list[i]);
  209. printf("])\n");
  210. printf(xstr(FUNCTION_UNDER_TEST) "_perf: %dx%d %d\n", m, TEST_LEN(m), nerrs);
  211. memcpy(src_err_list, err_list, nerrs);
  212. memset(src_in_err, 0, TEST_SOURCES);
  213. for (i = 0; i < nerrs; i++)
  214. src_in_err[src_err_list[i]] = 1;
  215. // Allocate the arrays
  216. for (i = 0; i < m; i++) {
  217. if (posix_memalign(&buf, 64, TEST_LEN(m))) {
  218. printf("Error allocating buffers\n");
  219. goto exit;
  220. }
  221. buffs[i] = buf;
  222. }
  223. for (i = 0; i < (m - k); i++) {
  224. if (posix_memalign(&buf, 64, TEST_LEN(m))) {
  225. printf("Error allocating buffers\n");
  226. goto exit;
  227. }
  228. temp_buffs[i] = buf;
  229. memset(temp_buffs[i], 0, TEST_LEN(m)); // initialize the destination buffer to be zero for update function
  230. }
  231. for (i = 0; i < TEST_SOURCES; i++) {
  232. if (posix_memalign(&buf, 64, TEST_LEN(m))) {
  233. printf("Error allocating buffers\n");
  234. goto exit;
  235. }
  236. update_buffs[i] = buf;
  237. memset(update_buffs[i], 0, TEST_LEN(m)); // initialize the destination buffer to be zero for update function
  238. }
  239. for (i = 0; i < TEST_SOURCES; i++) {
  240. if (posix_memalign(&buf, 64, TEST_LEN(m))) {
  241. printf("Error allocating buffers\n");
  242. goto exit;
  243. }
  244. perf_update_buffs[i] = buf;
  245. memset(perf_update_buffs[i], 0, TEST_LEN(m)); // initialize the destination buffer to be zero for update function
  246. }
  247. // Make random data
  248. for (i = 0; i < k; i++)
  249. for (j = 0; j < TEST_LEN(m); j++) {
  250. buffs[i][j] = rand();
  251. update_buffs[i][j] = buffs[i][j];
  252. }
  253. gf_gen_rs_matrix(a, m, k);
  254. encode_update_test_ref(m, k, g_tbls, buffs, a);
  255. encode_update_test(m, k, g_tbls, update_buffs, a);
  256. for (i = 0; i < m - k; i++) {
  257. if (0 != memcmp(update_buffs[k + i], buffs[k + i], TEST_LEN(m))) {
  258. printf("\nupdate_buffs%d :", i);
  259. dump(update_buffs[k + i], 25);
  260. printf("buffs%d :", i);
  261. dump(buffs[k + i], 25);
  262. goto exit;
  263. }
  264. }
  265. #ifdef DO_REF_PERF
  266. // Start encode test
  267. BENCHMARK(&start, BENCHMARK_TIME, encode_update_test_ref(m, k, g_tbls, buffs, a));
  268. printf(xstr(REF_FUNCTION) TEST_TYPE_STR ": ");
  269. perf_print(start, (long long)(TEST_LEN(m)) * (m));
  270. #endif
  271. // Start encode test
  272. BENCHMARK(&start, BENCHMARK_TIME,
  273. encode_update_test(m, k, g_tbls, perf_update_buffs, a));
  274. printf(xstr(FUNCTION_UNDER_TEST) TEST_TYPE_STR ": ");
  275. perf_print(start, (long long)(TEST_LEN(m)) * (m));
  276. // Start encode test
  277. BENCHMARK(&start, BENCHMARK_TIME,
  278. // Make parity vects
  279. ec_init_tables(k, m - k, &a[k * k], g_tbls);
  280. FUNCTION_UNDER_TEST(TEST_LEN(m), k, m - k, 0, g_tbls, perf_update_buffs[0],
  281. &perf_update_buffs[k]));
  282. printf(xstr(FUNCTION_UNDER_TEST) "_single_src" TEST_TYPE_STR ": ");
  283. perf_print(start, (long long)(TEST_LEN(m)) * (m - k + 1));
  284. // Start encode test
  285. BENCHMARK(&start, BENCHMARK_TIME,
  286. // Make parity vects
  287. FUNCTION_UNDER_TEST(TEST_LEN(m), k, m - k, 0, g_tbls, perf_update_buffs[0],
  288. &perf_update_buffs[k]));
  289. printf(xstr(FUNCTION_UNDER_TEST) "_single_src_simple" TEST_TYPE_STR ": ");
  290. perf_print(start, (long long)(TEST_LEN(m)) * (m - k + 1));
  291. for (i = k; i < m; i++) {
  292. memset(update_buffs[i], 0, TEST_LEN(m)); // initialize the destination buffer to be zero for update function
  293. }
  294. for (i = 0; i < k; i++) {
  295. FUNCTION_UNDER_TEST(TEST_LEN(m), k, m - k, i, g_tbls, update_buffs[i],
  296. &update_buffs[k]);
  297. }
  298. decode_test(m, k, update_buffs, recov, a, src_in_err, src_err_list,
  299. nerrs, g_tbls, temp_buffs);
  300. BENCHMARK(&start, BENCHMARK_TIME, check =
  301. decode_test(m, k, update_buffs, recov, a, src_in_err, src_err_list,
  302. nerrs, g_tbls, perf_update_buffs));
  303. if (check) {
  304. printf("BAD_MATRIX\n");
  305. ret = check;
  306. goto exit;
  307. }
  308. for (i = 0; i < nerrs; i++) {
  309. if (0 != memcmp(temp_buffs[i], update_buffs[src_err_list[i]], TEST_LEN(m))) {
  310. printf("Fail error recovery (%d, %d, %d) - \n", m, k, nerrs);
  311. goto exit;
  312. }
  313. }
  314. printf(xstr(FUNCTION_UNDER_TEST) "_decode" TEST_TYPE_STR ": ");
  315. perf_print(start, (long long)(TEST_LEN(m)) * (k + nerrs));
  316. printf("done all: Pass\n");
  317. ret = 0;
  318. exit:
  319. free(err_list);
  320. for (i = 0; i < TEST_SOURCES; i++) {
  321. free(buffs[i]);
  322. free(temp_buffs[i]);
  323. free(update_buffs[i]);
  324. free(perf_update_buffs[i]);
  325. }
  326. return ret;
  327. }