mandelbrot.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2019 Mael Keryell
  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 <stdlib.h>
  18. #include <starpu.h>
  19. #include "cpu_mandelbrot.h"
  20. void cpu_mandelbrot(void **, void *);
  21. void gpu_mandelbrot(void **, void *);
  22. static struct starpu_perfmodel model =
  23. {
  24. .type = STARPU_HISTORY_BASED,
  25. .symbol = "history_perf"
  26. };
  27. static struct starpu_codelet cl =
  28. {
  29. .cpu_funcs = {cpu_mandelbrot},
  30. //.cuda_funcs = {gpu_mandelbrot},
  31. .nbuffers = 1,
  32. .modes = {STARPU_W},
  33. .model = &model
  34. };
  35. void mandelbrot_with_starpu(long long *pixels, struct params *p, long long dim, long long nslicesx)
  36. {
  37. starpu_data_handle_t pixels_handle;
  38. starpu_matrix_data_register(&pixels_handle, STARPU_MAIN_RAM, (uintptr_t)pixels, dim, dim, dim, sizeof(long long));
  39. struct starpu_data_filter horiz =
  40. {
  41. .filter_func = starpu_matrix_filter_block,
  42. .nchildren = nslicesx
  43. };
  44. starpu_data_partition(pixels_handle, &horiz);
  45. long long taskx;
  46. for (taskx = 0; taskx < nslicesx; taskx++)
  47. {
  48. struct starpu_task *task = starpu_task_create();
  49. task->cl = &cl;
  50. task->handles[0] = starpu_data_get_child(pixels_handle, taskx);
  51. task->cl_arg = p;
  52. task->cl_arg_size = sizeof(*p);
  53. if (starpu_task_submit(task)!=0) fprintf(stderr,"submit task error\n");
  54. }
  55. starpu_task_wait_for_all();
  56. starpu_data_unpartition(pixels_handle, STARPU_MAIN_RAM);
  57. starpu_data_unregister(pixels_handle);
  58. }
  59. void pixels2img(long long *pixels, long long width, long long height, const char *filename)
  60. {
  61. FILE *fp = fopen(filename, "w");
  62. if (!fp)
  63. return;
  64. int MAPPING[16][3] = {{66,30,15},{25,7,26},{9,1,47},{4,4,73},{0,7,100},{12,44,138},{24,82,177},{57,125,209},{134,181,229},{211,236,248},{241,233,191},{248,201,95},{255,170,0},{204,128,0},{153,87,0},{106,52,3}};
  65. fprintf(fp, "P3\n%lld %lld\n255\n", width, height);
  66. long long i, j;
  67. for (i = 0; i < height; ++i)
  68. {
  69. for (j = 0; j < width; ++j)
  70. {
  71. fprintf(fp, "%d %d %d ", MAPPING[pixels[j*width+i]][0], MAPPING[pixels[j*width+i]][1], MAPPING[pixels[j*width+i]][2]);
  72. }
  73. }
  74. fclose(fp);
  75. }
  76. double min_times(double cr, double ci, long long dim, long long nslices)
  77. {
  78. long long *pixels = calloc(dim*dim, sizeof(long long));
  79. struct params *p = calloc(nslices, sizeof(struct params));
  80. double t_min = 0;
  81. long long i;
  82. for (i=0; i<nslices; i++)
  83. {
  84. p[i].centerr = cr;
  85. p[i].centeri = ci;
  86. p[i].offset = i*dim/nslices;
  87. p[i].dim = dim;
  88. }
  89. double start, stop, exec_t;
  90. for (i = 0; i < 10; i++)
  91. {
  92. start = starpu_timing_now(); // starpu_timing_now() gives the time in microseconds.
  93. mandelbrot_with_starpu(pixels, &p[i], dim, nslices);
  94. stop = starpu_timing_now();
  95. exec_t = (stop-start)*1.e3;
  96. if (t_min==0 || t_min>exec_t)
  97. t_min = exec_t;
  98. }
  99. char filename[64];
  100. snprintf(filename, 64, "out%lld.ppm", dim);
  101. pixels2img(pixels,dim,dim,filename);
  102. free(pixels);
  103. free(p);
  104. return t_min;
  105. }
  106. void display_times(double cr, double ci, long long start_dim, long long step_dim, long long stop_dim, long long nslices)
  107. {
  108. long long dim;
  109. for (dim = start_dim; dim <= stop_dim; dim += step_dim)
  110. {
  111. printf("Dimension: %lld...\n", dim);
  112. double res = min_times(cr, ci, dim, nslices);
  113. res = res / dim / dim; // time per pixel
  114. printf("%lld %lf\n", dim, res);
  115. }
  116. }
  117. int main(int argc, char **argv)
  118. {
  119. if (argc != 7)
  120. {
  121. printf("Usage: %s cr ci start_dim step_dim stop_dim nslices(must divide dims)\n", argv[0]);
  122. return 1;
  123. }
  124. if (starpu_init(NULL) != EXIT_SUCCESS)
  125. {
  126. fprintf(stderr, "ERROR\n");
  127. return 77;
  128. }
  129. double cr = (float) atof(argv[1]);
  130. double ci = (float) atof(argv[2]);
  131. long long start_dim = atoll(argv[3]);
  132. long long step_dim = atoll(argv[4]);
  133. long long stop_dim = atoll(argv[5]);
  134. long long nslices = atoll(argv[6]);
  135. display_times(cr, ci, start_dim, step_dim, stop_dim, nslices);
  136. starpu_shutdown();
  137. return 0;
  138. }