matheus__serpa icon

parallel

matheus__serpa | PRO | 10/03/14 10:26:10 PM UTC | 0 ⭐ | 572 👁️ | Never ⏰ | []
C |

2.77 KB

|

None

|

0 👍

/

0 👎

/* Two-dimensional array access */
// Example of good memory access - Array a is accessed along the rows. This approach ensures good performance from the memory system
for (int i = 0; i < n; i ++)
   for (int j = 0; j < n; j++)
      sum += a[i][j];
 
// Example of bad memory access - Array a is accessed columnwise. This approach results in poor utilization of the memory system. The larger array, the worse its performance will be.
for (int j = 0; j < n; j++)
   for (int i = 0; i < n; i ++)
      sum += a[i][j];
 
 
/* Loop unrolling */
// A short loop nest - Loop overheads are relatively high when each iteration has a small number of operations.
for(int i = 1; i < n; i++){
   a[i] = b[i] + 1;
   c[i] = a[i] + a[i - 1] + b[i - 1];
}
 
// A unrolled loop - The loop has been unrolled by a factor of 2 to reduce the loop overheads.
for(int i = 1; i < n; i+= 2){
   a[i] = b[i] + 1;
   c[i] = a[i] + a[i - 1] + b[i - 1];
   a[i + 1] = b[i + 1] + 1;
   c[i + 1] = a[i + 1] + a[i] + b[i];
}
 
 
/* Loop fusion */
// A pair of loops that both access array a - The second loop reuses element a[i], but by the time it is executed, the cache line this element is part of may no longer be in the cache.
for(int i = 0; i < n; i++)
   a[i] = b[i]  * 2;
for(int i = 0; i < n; i ++){
   x[i] = x[i] * 2;
   c[i] = a[i] + 2;
}
 
// An example of loop fusion - The pair of loops have been combined and the statements reordered. This permits the values of array a to be immediately reused.
for(int i = 0; i < n; i ++){
   a[i] = b[i] * 2;
   c[i] = a[i] + 2;
   x[i] = x[i] * 2;
}
 
 
/* Loop fission */
// A loop with poor cache utilization and bad memory access - if we can split off the updates to array c from the rest of the work, loop interchange can be applied to fix this problem.
for(int i =0; i < n; i ++){
   c[i] = exp(i / n);
   for(int j = 0; j < m; j++){
      a[j][i] = b[j][i] + d[j] * e[i];
   }
}
 
// Loop fission - The loop nest here has been split into a pair of loops, followed by loop interchange applied to the second loop to improve cache usage.
for(int i = 0; i < n; i++)
   c[i] = exp(i / n);
 
for(int j = 0; j < m; j++)
   for(int i = 0; i < n; i++)
      a[j][i] = b[j][i] + d[j] * e[i];
 
 
/* Loop tiling */
// A nested loop implementing an array transpose operation - Loop interchange does not improve its use of cache or TLB. A fresh approach is needed.
for(int i = 0; i < n; i++)
   for(int j = 0; j < n; j++)
      b[i][j] = a[j][i];
 
// Loop tiling applied to matrix transpose - Here we have used loop tiling to split the inner loop into a pair of loops. This reduces TLB and cache misses.
for(int j1 = 0; j1 < n; j1 += nbj)
   for(int i = 0; i < n; i++)
      for(int j2 = 0; j2 < MIN(n - j1, nbj); j2++)
         b[i][j1 + j2] = a[j1 + j2][i];

Comments