We all know how to calculate matrix multiplication. Generally,We all use the following code.:
Copy codeThe Code is as follows: for (I = 0; I <n; ++ I)
For (j = 0; j <n; ++ j ){
Sum = 0;
For (k = 0; k <n; ++ k)
Sum + = A [I] [k] * B [k] [j];
C [I] [j] + = sum;
}
However, there is actually a better implementation method after the high-speed cache problem is taken into account:Copy codeThe Code is as follows:
For (I = 0; I <n; ++ I)
For (k = 0; k <n; ++ k ){
R = A [I] [k];
For (j = 0; j <n; ++ j)
C [I] [j] + = r * B [k] [j];
}
After a closer look, we will find that the two implementation semantics are equivalent, but the actual running efficiency of the latter is higher than that of the former.
So why?
This is because when the CPU reads data, it does not directly access the memory, but first checks whether there is data in the cache. If yes, it reads data directly from the cache. Reading data from the cache is much faster than reading data from the memory.
When the data is not cached, the CPU reads a data block including the data into the cache. If the program has a good local space, after the first miss of the cache, the subsequent data access can be completed directly in the cache. In addition to spatial locality (the program tends to reference data adjacent to the current data), there is also temporal locality (the program tends to reference recently referenced data ).
Return to matrix multiplication. (We only consider the internal loop)
The former has A good spatial locality for matrix A. If four elements can be cached at A time, each iteration only misses A for 0.25 times, but for B, it does not, therefore, B accesses by column and misses each access. Therefore, the total number of misses in each iteration is 1.25.
The latter has good locality for both matrix C and matrix B. Each iteration only misses 0.25 words, so the total number of misses is 0.5. The latter stores an extra storage (write to C [I] [j]) in each iteration, but even so, the latter runs more efficiently than the former.
All in all, if you want your program to run fast, you need to make more use of locality in the program, so that the cache can hold your data and reduce the number of visits. You need to know that the CPU can access L1 cache within three clock cycles, and access L2 cache at around 10 clock cycles. It takes hundreds of clock cycles to access the memory. Is it easy or slow? Is it clear?