disk_stdio.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2013 Corentin Salingue
  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 <fcntl.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <sys/stat.h>
  20. #include <sys/time.h>
  21. #include <starpu.h>
  22. #include <core/disk.h>
  23. #include <core/perfmodel/perfmodel.h>
  24. #ifdef STARPU_HAVE_WINDOWS
  25. #include <io.h>
  26. #endif
  27. #define NITER 64
  28. /* ------------------- use STDIO to write on disk ------------------- */
  29. struct starpu_stdio_obj {
  30. int descriptor;
  31. FILE * file;
  32. char * path;
  33. double size;
  34. };
  35. /* allocation memory on disk */
  36. static void *
  37. starpu_stdio_alloc (void *base, size_t size)
  38. {
  39. struct starpu_stdio_obj * obj = malloc(sizeof(struct starpu_stdio_obj));
  40. STARPU_ASSERT(obj != NULL);
  41. int id = -1;
  42. /* create template for mkstemp */
  43. unsigned int sizeBase = 16;
  44. while(sizeBase < (strlen(base)+7))
  45. sizeBase *= 2;
  46. char * baseCpy = malloc(sizeBase*sizeof(char));
  47. STARPU_ASSERT(baseCpy != NULL);
  48. char * tmp = "STARPU_XXXXXX";
  49. strcpy(baseCpy, (char *) base);
  50. strcat(baseCpy,tmp);
  51. #ifdef STARPU_HAVE_WINDOWS
  52. _mktemp(baseCpy);
  53. id = open(baseCpy, "rb+");
  54. #else
  55. id = mkstemp(baseCpy);
  56. #endif
  57. /* fail */
  58. if (id < 0)
  59. {
  60. free(obj);
  61. free(baseCpy);
  62. return NULL;
  63. }
  64. FILE * f = fdopen(id, "rb+");
  65. /* fail */
  66. if (f == NULL)
  67. {
  68. /* delete fic */
  69. free(obj);
  70. free(baseCpy);
  71. unlink(baseCpy);
  72. return NULL;
  73. }
  74. #ifdef STARPU_HAVE_WINDOWS
  75. int val = _chsize(id, size);
  76. #else
  77. int val = ftruncate(id,size);
  78. #endif
  79. /* fail */
  80. if (val < 0)
  81. {
  82. free(obj);
  83. free(baseCpy);
  84. unlink(baseCpy);
  85. return NULL;
  86. }
  87. obj->descriptor = id;
  88. obj->file = f;
  89. obj->path = baseCpy;
  90. obj->size = size;
  91. return (void *) obj;
  92. }
  93. /* free memory on disk */
  94. static void
  95. starpu_stdio_free (void *base STARPU_ATTRIBUTE_UNUSED, void *obj, size_t size STARPU_ATTRIBUTE_UNUSED)
  96. {
  97. struct starpu_stdio_obj * tmp = (struct starpu_stdio_obj *) obj;
  98. unlink(tmp->path);
  99. fclose(tmp->file);
  100. close(tmp->descriptor);
  101. free(tmp->path);
  102. free(tmp);
  103. }
  104. /* open an existing memory on disk */
  105. static void *
  106. starpu_stdio_open (void *base, void *pos, size_t size)
  107. {
  108. struct starpu_stdio_obj * obj = malloc(sizeof(struct starpu_stdio_obj));
  109. STARPU_ASSERT(obj != NULL);
  110. /* create template */
  111. unsigned int sizeBase = 16;
  112. while(sizeBase < (strlen(base)+strlen(pos)+1))
  113. sizeBase *= 2;
  114. char * baseCpy = malloc(sizeBase*sizeof(char));
  115. STARPU_ASSERT(baseCpy != NULL);
  116. strcpy(baseCpy,(char *) base);
  117. strcat(baseCpy,(char *) pos);
  118. int id = open(baseCpy, O_RDWR);
  119. if (id < 0)
  120. {
  121. free(obj);
  122. free(baseCpy);
  123. return NULL;
  124. }
  125. FILE * f = fdopen(id,"rb+");
  126. if (f == NULL)
  127. {
  128. free(obj);
  129. free(baseCpy);
  130. return NULL;
  131. }
  132. obj->descriptor = id;
  133. obj->file = f;
  134. obj->path = baseCpy;
  135. obj->size = size;
  136. return (void *) obj;
  137. }
  138. /* free memory without delete it */
  139. static void
  140. starpu_stdio_close (void *base STARPU_ATTRIBUTE_UNUSED, void *obj, size_t size STARPU_ATTRIBUTE_UNUSED)
  141. {
  142. struct starpu_stdio_obj * tmp = (struct starpu_stdio_obj *) obj;
  143. fclose(tmp->file);
  144. close(tmp->descriptor);
  145. free(tmp->path);
  146. free(tmp);
  147. }
  148. /* read the memory disk */
  149. static ssize_t
  150. starpu_stdio_read (void *base STARPU_ATTRIBUTE_UNUSED, void *obj, void *buf, off_t offset, size_t size)
  151. {
  152. struct starpu_stdio_obj * tmp = (struct starpu_stdio_obj *) obj;
  153. int res = fseek(tmp->file, offset, SEEK_SET);
  154. STARPU_ASSERT_MSG(res == 0, "Stdio read failed");
  155. ssize_t nb = fread (buf, 1, size, tmp->file);
  156. return nb;
  157. }
  158. /* write on the memory disk */
  159. static ssize_t
  160. starpu_stdio_write (void *base STARPU_ATTRIBUTE_UNUSED, void *obj, const void *buf, off_t offset, size_t size)
  161. {
  162. struct starpu_stdio_obj * tmp = (struct starpu_stdio_obj *) obj;
  163. int res = fseek(tmp->file, offset, SEEK_SET);
  164. STARPU_ASSERT_MSG(res == 0, "Stdio write failed");
  165. ssize_t nb = fwrite (buf, 1, size, tmp->file);
  166. return nb;
  167. }
  168. /* create a new copy of parameter == base */
  169. static void *
  170. starpu_stdio_plug (void *parameter)
  171. {
  172. char * tmp = malloc(sizeof(char)*(strlen(parameter)+1));
  173. STARPU_ASSERT(tmp != NULL);
  174. strcpy(tmp,(char *) parameter);
  175. return (void *) tmp;
  176. }
  177. /* free memory allocated for the base */
  178. static void
  179. starpu_stdio_unplug (void *base)
  180. {
  181. free(base);
  182. }
  183. static int
  184. get_stdio_bandwidth_between_disk_and_main_ram(unsigned node)
  185. {
  186. unsigned iter;
  187. double timing_slowness, timing_latency;
  188. struct timeval start;
  189. struct timeval end;
  190. srand (time (NULL));
  191. char * buf = malloc(SIZE_DISK_MIN*sizeof(char));
  192. STARPU_ASSERT(buf != NULL);
  193. /* allocate memory */
  194. void * mem = _starpu_disk_alloc(node, SIZE_DISK_MIN);
  195. /* fail to alloc */
  196. if (mem == NULL)
  197. return 0;
  198. struct starpu_stdio_obj * tmp = (struct starpu_stdio_obj *) mem;
  199. /* Measure upload slowness */
  200. gettimeofday(&start, NULL);
  201. for (iter = 0; iter < NITER; ++iter)
  202. {
  203. _starpu_disk_write(node, mem, buf, 0, SIZE_DISK_MIN);
  204. /* clean cache memory */
  205. int res = fflush (tmp->file);
  206. STARPU_ASSERT_MSG(res == 0, "Slowness computation failed \n");
  207. #ifdef STARPU_HAVE_WINDOWS
  208. res = _commit(tmp->descriptor);
  209. #else
  210. res = fsync(tmp->descriptor);
  211. #endif
  212. STARPU_ASSERT_MSG(res == 0, "Slowness computation failed \n");
  213. }
  214. gettimeofday(&end, NULL);
  215. timing_slowness = (double)((end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec));
  216. /* free memory */
  217. free(buf);
  218. buf = malloc(sizeof(char));
  219. STARPU_ASSERT(buf != NULL);
  220. /* Measure latency */
  221. gettimeofday(&start, NULL);
  222. for (iter = 0; iter < NITER; ++iter)
  223. {
  224. _starpu_disk_write(node, mem, buf, rand() % (SIZE_DISK_MIN -1) , 1);
  225. int res = fflush (tmp->file);
  226. STARPU_ASSERT_MSG(res == 0, "Latency computation failed");
  227. #ifdef STARPU_HAVE_WINDOWS
  228. res = _commit(tmp->descriptor);
  229. #else
  230. res = fsync(tmp->descriptor);
  231. #endif
  232. STARPU_ASSERT_MSG(res == 0, "Latency computation failed");
  233. }
  234. gettimeofday(&end, NULL);
  235. timing_latency = (double)((end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec));
  236. _starpu_disk_free(node, mem, SIZE_DISK_MIN);
  237. free(buf);
  238. _starpu_save_bandwidth_and_latency_disk((NITER/timing_slowness)*1000000, (NITER/timing_slowness)*1000000,
  239. timing_latency/NITER, timing_latency/NITER, node);
  240. return 1;
  241. }
  242. struct starpu_disk_ops starpu_disk_stdio_ops = {
  243. .alloc = starpu_stdio_alloc,
  244. .free = starpu_stdio_free,
  245. .open = starpu_stdio_open,
  246. .close = starpu_stdio_close,
  247. .read = starpu_stdio_read,
  248. .write = starpu_stdio_write,
  249. .plug = starpu_stdio_plug,
  250. .unplug = starpu_stdio_unplug,
  251. .copy = NULL,
  252. .bandwidth = get_stdio_bandwidth_between_disk_and_main_ram
  253. };