Computer Organization and Design assignements
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

126 lines
3.3 KiB

  1. /*!
  2. \file matmul.c
  3. \brief Matrix multiplication implementation.
  4. \author Nikos Pitsianis
  5. \author Dimitris Floros
  6. \author Christos Choutouridis 8997 <cchoutou@ece.auth.gr>
  7. \date 2020-05-05
  8. */
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <math.h>
  12. #include <sys/time.h>
  13. #include <assert.h>
  14. #define MAX_ITER 10
  15. #define sub2ind(i,j,n) (j) + (i)*(n)
  16. /*!
  17. * Square Matrix multiplication
  18. * \param C pointer to output matrix
  19. * \param A pointer to input matrix A
  20. * \param B pointer to input matrix B
  21. * \param n Size of matrices (both sizes)
  22. * \return none
  23. *
  24. * \note
  25. * This version executes row major order ijk
  26. */
  27. void matrixMult(float * const C, float const * const A, float const * const B, int const n) {
  28. for (int i = 0; i < n; i++) { /* rows */
  29. for (int j = 0; j < n; j++) { /* cols */
  30. C[ sub2ind(i,j,n) ] = 0; /* initialize output value */
  31. for (int k = 0; k < n; k++) { /* accumulate products */
  32. C[ sub2ind(i,j,n) ] +=
  33. A[ sub2ind(i,k,n) ] * B[ sub2ind(k,j,n) ];
  34. }
  35. }
  36. }
  37. }
  38. /*!
  39. * Initialize matrix with random indices and return the matrix pointer.
  40. *
  41. * \param n The size of the matrix (both of them)
  42. * \return Pointer to allocated and initialized matrix
  43. */
  44. float * matrixInit(int const n) {
  45. float *M = (float *) malloc( n*n*sizeof(float) );
  46. for (int i = 0; i < n; i++) /* rows */
  47. for (int j = 0; j < n; j++) /* cols */
  48. M[ sub2ind(i,j,n) ] = (float)rand()/(float)(RAND_MAX);
  49. return M;
  50. }
  51. int cmpfunc (const void * a, const void * b) {
  52. double v =*(double*)a - *(double*)b;
  53. return (v < 0) ? -1 : (v > 0) ? 1 : 0;
  54. }
  55. /*!
  56. * A unit testing like main function to profile our code
  57. */
  58. int main(int argc, char **argv)
  59. {
  60. struct timeval start, end; /* time structs */
  61. double time[MAX_ITER] = {0.0}; /* execution time array in ms */
  62. float *A, *B, *C; /* matrix declarations */
  63. int n; /* matrix size */
  64. /* read matrix size (or use default) */
  65. if (argc != 2){
  66. fprintf( stderr, "Usage:\n %s n\n where n is the matrix size.\n",
  67. argv[0]);
  68. exit(1);
  69. }
  70. n = atoi( argv[1] );
  71. /* initialize matrices */
  72. A = matrixInit( n );
  73. B = matrixInit( n );
  74. C = (float *) malloc( n*n*sizeof(float) );
  75. /* compute matrix multiplication */
  76. for (int it = 0; it < MAX_ITER; it++) {
  77. gettimeofday(&start, NULL);
  78. matrixMult( C, A, B, n );
  79. gettimeofday(&end, NULL);
  80. time[it] = (end.tv_sec - start.tv_sec) * 1000.0 + /* sec to ms */
  81. (end.tv_usec - start.tv_usec) / 1000.0; /* us to ms */
  82. printf("Iter: %d Time: %f ms\n", it, time[it]);
  83. }
  84. /* we need to use the result -- verify it */
  85. for (int i = 0; i < n; i++) { /* rows */
  86. for (int j = 0; j < n; j++) { /* cols */
  87. float gold = 0;
  88. for (int k = 0; k < n; k++) { /* accumulate products */
  89. gold += A[ sub2ind(i,k,n) ] * B[ sub2ind(k,j,n) ];
  90. }
  91. assert( (gold - C[sub2ind(i,j,n)]) < 1e-3 );
  92. }
  93. }
  94. // median calculation
  95. qsort ((void*)time, MAX_ITER, sizeof(time[0]), cmpfunc);
  96. printf("Median: %f [msec]\n", (MAX_ITER % 2) ?
  97. time[MAX_ITER/2] :
  98. (time[MAX_ITER/2] + time[MAX_ITER/2 -1]) /2
  99. );
  100. }