这是一个本人学习 csapp 的 learning 库
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
3.2 KiB

  1. /* mountain.c - Generate the memory mountain. */
  2. /* $begin mountainmain */
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include "fcyc2.h" /* measurement routines */
  6. #include "clock.h" /* routines to access the cycle counter */
  7. #define MINBYTES (1 << 14) /* First working set size */
  8. #define MAXBYTES (1 << 27) /* Last working set size */
  9. #define MAXSTRIDE 15 /* Stride x8 bytes */
  10. #define MAXELEMS MAXBYTES/sizeof(long)
  11. /* $begin mountainfuns */
  12. long data[MAXELEMS]; /* The global array we'll be traversing */
  13. /* $end mountainfuns */
  14. /* $end mountainmain */
  15. void init_data(long *data, int n);
  16. int test(int elems, int stride);
  17. double run(int size, int stride, double Mhz);
  18. /* $begin mountainmain */
  19. int main()
  20. {
  21. int size; /* Working set size (in bytes) */
  22. int stride; /* Stride (in array elements) */
  23. double Mhz; /* Clock frequency */
  24. FILE *fp = NULL;
  25. fp = fopen("mountain.txt", "w+");
  26. init_data(data, MAXELEMS); /* Initialize each element in data */
  27. Mhz = mhz(0); /* Estimate the clock frequency */
  28. /* $end mountainmain */
  29. /* Not shown in the text */
  30. fprintf(fp, "Clock frequency is approx. %.1f MHz\n", Mhz);
  31. fprintf(fp, "Memory mountain (MB/sec)\n");
  32. fprintf(fp, "\t");
  33. for (stride = 1; stride <= MAXSTRIDE; stride++)
  34. fprintf(fp, "s%d\t", stride);
  35. fprintf(fp, "\n");
  36. /* $begin mountainmain */
  37. for (size = MAXBYTES; size >= MINBYTES; size >>= 1) {
  38. /* $end mountainmain */
  39. /* Not shown in the text */
  40. if (size > (1 << 20))
  41. fprintf(fp, "%dm\t", size / (1 << 20));
  42. else
  43. fprintf(fp, "%dk\t", size / 1024);
  44. /* $begin mountainmain */
  45. for (stride = 1; stride <= MAXSTRIDE; stride++) {
  46. fprintf(fp, "%.0f\t", run(size, stride, Mhz));
  47. }
  48. fprintf(fp, "\n");
  49. }
  50. fclose(fp);
  51. exit(0);
  52. }
  53. /* $end mountainmain */
  54. /* init_data - initializes the array */
  55. void init_data(long *data, int n)
  56. {
  57. int i;
  58. for (i = 0; i < n; i++)
  59. data[i] = i;
  60. }
  61. /* $begin mountainfuns */
  62. /* test - Iterate over first "elems" elements of array "data" with
  63. * stride of "stride", using 4x4 loop unrolling.
  64. */
  65. int test(int elems, int stride)
  66. {
  67. long i, sx2 = stride*2, sx3 = stride*3, sx4 = stride*4;
  68. long acc0 = 0, acc1 = 0, acc2 = 0, acc3 = 0;
  69. long length = elems;
  70. long limit = length - sx4;
  71. /* Combine 4 elements at a time */
  72. for (i = 0; i < limit; i += sx4) {
  73. acc0 = acc0 + data[i];
  74. acc1 = acc1 + data[i+stride];
  75. acc2 = acc2 + data[i+sx2];
  76. acc3 = acc3 + data[i+sx3];
  77. }
  78. /* Finish any remaining elements */
  79. for (; i < length; i += stride) {
  80. acc0 = acc0 + data[i];
  81. }
  82. return ((acc0 + acc1) + (acc2 + acc3));
  83. }
  84. /* run - Run test(elems, stride) and return read throughput (MB/s).
  85. * "size" is in bytes, "stride" is in array elements, and Mhz is
  86. * CPU clock frequency in Mhz.
  87. */
  88. double run(int size, int stride, double Mhz)
  89. {
  90. double cycles;
  91. int elems = size / sizeof(double);
  92. test(elems, stride); /* Warm up the cache */ //line:mem:warmup
  93. cycles = fcyc2(test, elems, stride, 0); /* Call test(elems,stride) */ //line:mem:fcyc
  94. return (size / stride) / (cycles / Mhz); /* Convert cycles to MB/s */ //line:mem:bwcompute
  95. }
  96. /* $end mountainfuns */