mandelbrot.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*
  2. * StarPU
  3. * Copyright (C) Université Bordeaux 1, CNRS 2008-2010 (see AUTHORS file)
  4. *
  5. * This program 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. * This program 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 <starpu.h>
  17. #ifdef STARPU_HAVE_X11
  18. #include <X11/Xlib.h>
  19. #include <X11/Xutil.h>
  20. #endif
  21. /* NB: The X11 code is inspired from the http://locklessinc.com/articles/mandelbrot/ article */
  22. static int nblocks = 32;
  23. static int height = 1280;
  24. static int width = 1600;
  25. static int maxIt = 20000;
  26. static double leftX = -0.745;
  27. static double rightX = -0.74375;
  28. static double topY = .15;
  29. static double bottomY = .14875;
  30. #ifdef STARPU_HAVE_X11
  31. /* X11 data */
  32. static Display *dpy;
  33. static Window win;
  34. static XImage *bitmap;
  35. static GC gc;
  36. static KeySym Left=-1, Right, Down, Up, Alt ;
  37. static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  38. static void exit_x11(void)
  39. {
  40. XDestroyImage(bitmap);
  41. XDestroyWindow(dpy, win);
  42. XCloseDisplay(dpy);
  43. }
  44. static void init_x11(int width, int height, unsigned *buffer)
  45. {
  46. /* Attempt to open the display */
  47. dpy = XOpenDisplay(NULL);
  48. /* Failure */
  49. if (!dpy)
  50. exit(0);
  51. unsigned long white = WhitePixel(dpy,DefaultScreen(dpy));
  52. unsigned long black = BlackPixel(dpy,DefaultScreen(dpy));
  53. win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
  54. width, height, 0, black, white);
  55. /* We want to be notified when the window appears */
  56. XSelectInput(dpy, win, StructureNotifyMask);
  57. /* Make it appear */
  58. XMapWindow(dpy, win);
  59. XTextProperty tp;
  60. char name[128] = "Mandelbrot";
  61. char *n = name;
  62. Status st = XStringListToTextProperty(&n, 1, &tp);
  63. if (st)
  64. XSetWMName(dpy, win, &tp);
  65. /* Wait for the MapNotify event */
  66. XFlush(dpy);
  67. int depth = DefaultDepth(dpy, DefaultScreen(dpy));
  68. Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
  69. /* Make bitmap */
  70. bitmap = XCreateImage(dpy, visual, depth,
  71. ZPixmap, 0, (char *)buffer,
  72. width, height, 32, 0);
  73. /* Init GC */
  74. gc = XCreateGC(dpy, win, 0, NULL);
  75. XSetForeground(dpy, gc, black);
  76. XSelectInput(dpy, win, ExposureMask | KeyPressMask | StructureNotifyMask);
  77. Atom wmDeleteMessage;
  78. wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
  79. XSetWMProtocols(dpy, win, &wmDeleteMessage, 1);
  80. Left = XStringToKeysym ("Left");
  81. Right = XStringToKeysym ("Right");
  82. Up = XStringToKeysym ("Up");
  83. Down = XStringToKeysym ("Down");
  84. Alt = XStringToKeysym ("Alt");
  85. }
  86. #endif
  87. static void compute_block(void *descr[], void *cl_arg)
  88. {
  89. int ix, iy;
  90. int iby, block_size;
  91. double stepX, stepY;
  92. starpu_unpack_cl_args(cl_arg, &iby, &block_size, &stepX, &stepY);
  93. unsigned *data = (unsigned *)STARPU_VECTOR_GET_PTR(descr[0]);
  94. int local_iy;
  95. for (local_iy = 0; local_iy < block_size; local_iy++)
  96. {
  97. iy = iby*block_size + local_iy;
  98. for (ix = 0; ix < width; ix++)
  99. {
  100. double cx = leftX + ix * stepX;
  101. double cy = topY - iy * stepY;
  102. // Z = X+I*Y
  103. double x = 0;
  104. double y = 0;
  105. int it;
  106. for (it = 0; it < maxIt; it++)
  107. {
  108. double x2 = x*x;
  109. double y2 = y*y;
  110. // Stop iterations when |Z| > 2
  111. if (x2 + y2 > 4.0)
  112. break;
  113. double twoxy = 2.0*x*y;
  114. // Z = Z^2 + C
  115. x = x2 - y2 + cx;
  116. y = twoxy + cy;
  117. }
  118. unsigned int v = STARPU_MIN((1024*((float)(it)/(2000))), 256);
  119. data[ix + local_iy*width] = (v<<16|(255-v)<<8);
  120. }
  121. }
  122. }
  123. static starpu_codelet mandelbrot_cl = {
  124. .where = STARPU_CPU,
  125. .type = STARPU_SEQ,
  126. .cpu_func = compute_block,
  127. .nbuffers = 1
  128. };
  129. #ifdef STARPU_HAVE_X11
  130. static int handle_events(void)
  131. {
  132. XEvent event;
  133. XNextEvent(dpy, &event);
  134. KeySym key;
  135. char text[255];
  136. if (event.type == KeyPress)
  137. {
  138. XLookupString(&event.xkey,text,255,&key,0);
  139. if (key == Left)
  140. {
  141. double widthX = rightX - leftX;
  142. leftX -= 0.25*widthX;
  143. rightX -= 0.25*widthX;
  144. }
  145. else if (key == Right)
  146. {
  147. double widthX = rightX - leftX;
  148. leftX += 0.25*widthX;
  149. rightX += 0.25*widthX;
  150. }
  151. else if (key == Up)
  152. {
  153. double heightY = topY - bottomY;
  154. topY += 0.25*heightY;
  155. bottomY += 0.25*heightY;
  156. }
  157. else if (key == Down)
  158. {
  159. double heightY = topY - bottomY;
  160. topY -= 0.25*heightY;
  161. bottomY -= 0.25*heightY;
  162. }
  163. else {
  164. double widthX = rightX - leftX;
  165. double heightY = topY - bottomY;
  166. if (text[0] == '-')
  167. {
  168. /* Zoom out */
  169. leftX -= 0.125*widthX;
  170. rightX += 0.125*widthX;
  171. topY += 0.125*heightY;
  172. bottomY -= 0.125*heightY;
  173. }
  174. else if (text[0] == '+')
  175. {
  176. /* Zoom in */
  177. leftX += 0.125*widthX;
  178. rightX -= 0.125*widthX;
  179. topY -= 0.125*heightY;
  180. bottomY += 0.125*heightY;
  181. }
  182. }
  183. if (text[0]=='q') {
  184. return -1;
  185. }
  186. }
  187. if (event.type==ButtonPress) {
  188. /* tell where the mouse Button was Pressed */
  189. printf("You pressed a button at (%i,%i)\n",
  190. event.xbutton.x,event.xbutton.y);
  191. }
  192. return 0;
  193. }
  194. #endif
  195. int main(int argc, char **argv)
  196. {
  197. unsigned *buffer;
  198. buffer = malloc(height*width*sizeof(unsigned));
  199. #ifdef STARPU_HAVE_X11
  200. init_x11(width, height, buffer);
  201. #endif
  202. int block_size = height/nblocks;
  203. STARPU_ASSERT((height % nblocks) == 0);
  204. starpu_init(NULL);
  205. starpu_data_handle block_handles[nblocks];
  206. int iby;
  207. for (iby = 0; iby < nblocks; iby++)
  208. {
  209. unsigned *data = &buffer[iby*block_size*width];
  210. starpu_vector_data_register(&block_handles[iby], 0,
  211. (uintptr_t)data, block_size*width, sizeof(unsigned));
  212. }
  213. while (1)
  214. {
  215. double stepX = (rightX - leftX)/width;
  216. double stepY = (topY - bottomY)/height;
  217. for (iby = 0; iby < nblocks; iby++)
  218. {
  219. starpu_insert_task(&mandelbrot_cl,
  220. STARPU_VALUE, &iby, sizeof(iby),
  221. STARPU_VALUE, &block_size, sizeof(block_size),
  222. STARPU_VALUE, &stepX, sizeof(stepX),
  223. STARPU_VALUE, &stepY, sizeof(stepY),
  224. STARPU_W, block_handles[iby],
  225. 0);
  226. }
  227. for (iby = 0; iby < nblocks; iby++)
  228. {
  229. starpu_data_acquire(block_handles[iby], STARPU_R);
  230. #ifdef STARPU_HAVE_X11
  231. pthread_mutex_lock(&mutex);
  232. XPutImage(dpy, win, gc, bitmap,
  233. 0, iby*block_size,
  234. 0, iby*block_size,
  235. width, block_size);
  236. pthread_mutex_unlock(&mutex);
  237. #endif
  238. starpu_data_release(block_handles[iby]);
  239. }
  240. #ifdef STARPU_HAVE_X11
  241. if (handle_events())
  242. break;
  243. #endif
  244. }
  245. #ifdef STARPU_HAVE_X11
  246. exit_x11();
  247. #endif
  248. starpu_shutdown();
  249. return 0;
  250. }