bandwidth.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2009-2020 Université de Bordeaux, CNRS (LaBRI UMR 5800), Inria
  4. *
  5. * StarPU is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU Lesser General Public License as published by
  7. * the Free Software Foundation; either version 2.1 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * StarPU is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. *
  14. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  15. */
  16. #include <stdio.h>
  17. #include <unistd.h>
  18. #include <starpu.h>
  19. #include "../helper.h"
  20. /*
  21. * Measure the memory bandwidth available to kernels depending on the number of
  22. * kernels and number of idle workers.
  23. */
  24. /* Must be bigger than available cache size per core, 64MiB should be enough */
  25. static size_t size = 64UL << 20;
  26. static int iter = 30;
  27. static int ncpus;
  28. static starpu_pthread_barrier_t barrier;
  29. static float *result;
  30. void bw_func(void *descr[], void *arg)
  31. {
  32. void *src = malloc(size);
  33. void *dst = malloc(size);
  34. unsigned i;
  35. double start, stop;
  36. memset(src, 0, size);
  37. STARPU_PTHREAD_BARRIER_WAIT(&barrier);
  38. start = starpu_timing_now();
  39. for (i = 0; i < iter; i++)
  40. memcpy(dst, src, size);
  41. stop = starpu_timing_now();
  42. STARPU_PTHREAD_BARRIER_WAIT(&barrier);
  43. result[starpu_worker_get_id()] = (size*iter) / (stop - start);
  44. free(src);
  45. free(dst);
  46. }
  47. static struct starpu_codelet bw_codelet =
  48. {
  49. .cpu_funcs = {bw_func},
  50. .model = NULL,
  51. .nbuffers = 0,
  52. };
  53. static void usage(char **argv)
  54. {
  55. fprintf(stderr, "Usage: %s [-n iter] [-s size (MB)]]\n", argv[0]);
  56. exit(EXIT_FAILURE);
  57. }
  58. static void parse_args(int argc, char **argv)
  59. {
  60. int c;
  61. while ((c = getopt(argc, argv, "n:s:b:i:h")) != -1)
  62. switch(c)
  63. {
  64. case 'n':
  65. iter = atoi(optarg);
  66. break;
  67. case 's':
  68. size = (long)atoi(optarg) << 20;
  69. break;
  70. case 'h':
  71. usage(argv);
  72. break;
  73. }
  74. }
  75. static float bench(int *argc, char ***argv, unsigned nbusy, unsigned nidle)
  76. {
  77. int ret;
  78. unsigned i;
  79. struct starpu_conf conf;
  80. float bw;
  81. starpu_conf_init(&conf);
  82. conf.ncuda = 0;
  83. conf.nopencl = 0;
  84. conf.nmic = 0;
  85. conf.nmpi_ms = 0;
  86. conf.ncpus = nbusy + nidle;
  87. ret = starpu_initialize(&conf, argc, argv);
  88. if (ret == -ENODEV) return STARPU_TEST_SKIPPED;
  89. STARPU_CHECK_RETURN_VALUE(ret, "starpu_init");
  90. STARPU_PTHREAD_BARRIER_INIT(&barrier, NULL, nbusy);
  91. for (i = 0; i < nbusy; i++)
  92. {
  93. struct starpu_task *task = starpu_task_create();
  94. task->cl = &bw_codelet;
  95. task->execute_on_a_specific_worker = 1;
  96. task->workerid = i;
  97. ret = starpu_task_submit(task);
  98. STARPU_CHECK_RETURN_VALUE(ret, "starpu_task_submit");
  99. }
  100. starpu_task_wait_for_all();
  101. starpu_shutdown();
  102. for (bw = 0., i = 0; i < nbusy; i++)
  103. {
  104. bw += result[i];
  105. }
  106. return bw;
  107. }
  108. int main(int argc, char **argv)
  109. {
  110. int ret;
  111. unsigned n;
  112. struct starpu_conf conf;
  113. float alone, idle;
  114. parse_args(argc, argv);
  115. starpu_conf_init(&conf);
  116. conf.ncuda = 0;
  117. conf.nopencl = 0;
  118. conf.nmic = 0;
  119. conf.nmpi_ms = 0;
  120. ret = starpu_initialize(&conf, &argc, &argv);
  121. if (ret == -ENODEV) return STARPU_TEST_SKIPPED;
  122. STARPU_CHECK_RETURN_VALUE(ret, "starpu_init");
  123. ncpus = starpu_cpu_worker_get_count();
  124. starpu_shutdown();
  125. result = malloc(ncpus * sizeof(result[0]));
  126. printf("# nw\talone\t\t+idle\t\tidle efficiency\n");
  127. for (n = 1; n <= ncpus; n++)
  128. {
  129. alone = bench(&argc, &argv, n, 0);
  130. idle = bench(&argc, &argv, n, ncpus-n);
  131. printf("%d\t%f\t%f\t%f\n", n, alone/1000, idle/1000, idle*100/alone);
  132. }
  133. free(result);
  134. return EXIT_SUCCESS;
  135. enodev:
  136. fprintf(stderr, "WARNING: No one can execute this task\n");
  137. free(result);
  138. starpu_shutdown();
  139. return STARPU_TEST_SKIPPED;
  140. }