2015-06-16 7 views
1

Приветствую вас, дорогие земляне!Много промахов кеша, умножение матричной матрицы

Это обзор:

Я делаю разреженную матрицу умножения, где у меня есть два плотных матриц, но я заинтересован только в некоторых элементах производства. У меня есть две матрицы и один 2d индексный массив:

float * A:[M*K] 
float * B:[N*K] 
int [][] idx: [M][nSelection] (that is there are nselection rows in B, per row in matrix A that I want to multiply) 

и я хочу, чтобы вычислить:

out=A*B' // but of course only for the indices i,j where idx[i][k]=j for some k. 

Это зернистость материи: Я хочу, чтобы держать вещи в процессоре кэш, пока я размножая умножаем 16 поплавки в то время:

for (int kk = 0; kk < K; kk+=KK){ 
    int begin = 0; 
    int end = M; 
     for (int i = begin; i < end; i++){ 
      for (int j = 0; j < numberToAccept; j++){ 
       int theid = idx[i * numberToAccept + j]; 
       tempOut[i*numberToAccept+j] += blas_function_for_dotProduct(KK, A+i*K + kk, 1, B+theid*K + kk, 1); 
      } 
     } 
    } 

числа Я работаю с являются:

M = 2048; N=10240; K=4096; nSelection=100; 

Таким образом, идея заключается в том, что если я разобрать матрицы в маленьких частях маленьких частями (в направлении KK в кусках 16 поплавков = 1 cacheline) Я иметь возможность загружать обе матрицы только один раз. То есть, матрица A загружается последовательно, поэтому, кроме первой загрузки каждой строки, все остальные нагрузки должны быть хитами. матрица B загружается в случайном порядке, но поскольку я обрабатываю все это в кусках 64 байта (16 поплавков), тогда для этого потребуется 640 КБ. У меня 6 МБ L1, поэтому он должен оставаться там, если процессор использует LRU.

Я использую Valgrind, чтобы посмотреть на кэш-промахов и это то, что я получаю:

==3264== D refs:  2,383,524,642 (2,272,927,073 rd + 110,597,569 wr) 
==3264== D1 misses:  114,096,428 ( 113,982,278 rd +  114,150 wr) 
==3264== LLd misses:  95,822,173 ( 95,736,938 rd +  85,235 wr) 
==3264== D1 miss rate:   4.7% (   5.0%  +   0.1% ) 
==3264== LLd miss rate:   4.0% (   4.2%  +   0.0% ) 

Также я получаю тот же результат, если доступ предсказуем (подсчитывая).

Я получаю тот же результат с N = 512. но при N = 256, я вдруг получить хиты кэш (произвольного доступа):

==16546== D refs:  2,383,525,914 (2,272,928,002 rd + 110,597,912 wr) 
==16546== D1 misses:  114,096,557 ( 113,982,392 rd +  114,165 wr) 
==16546== LLd misses:  1,372,862 ( 1,287,624 rd +  85,238 wr) 
==16546== D1 miss rate:   4.7% (   5.0%  +   0.1% ) 
==16546== LLd miss rate:   0.0% (   0.0%  +   0.0% ) 

Дело в том, что у меня есть кэш 6MB на мой мобильный Core i7. И 512 * 16 * размер поплавка - 23 КБ. Так почему я получаю так много промахов? (Я написал большую часть этой вчерашней ночи, сегодня я нашел ответ.

ответ

1

Его ассоциативность кеша. Мой l3 - 12-канальный ассоциативный, я не делал вычислений, но менял K на 4 * 1024 + 16 дает мне удары полностью!

Смежные вопросы