Если вы говорите об использовании кешей, вы можете захотеть сделать что-то, называемое мозаикой цикла. Вы разбиваете цикл на плитки, так что внутренняя часть цикла сохраняется в кеше (который в наши дни довольно велик). Таким образом, ваш цикл превратится во что-то вроде (если вы передаете матрицы в функцию с помощью указателей)
for(j=0;j<size;j+=t)
for(k=0;k<size;k+=t)
for(i=0;i<size;i+=t)
for(ii=i;ii<MIN(i+t,size);ii++)
for(jj=j;jj<MIN(j+t,size);jj++)
{
var=*(c+ii * size+jj); //Var is a scalar variable
for(kk=k;kk<MIN(k+t,size);kk++)
{
var = var + *(a+ii *size +kk) * *(bt +jj * size+ kk);
}
*(c+ii *size +jj) = var;
}
Значение t варьируется в зависимости от полученного ускорения. Может быть t = 64 128 256 и так далее. Есть много других методов, которые вы можете использовать здесь. Мозаика цикла — это всего лишь один из методов эффективного использования кэша. Кроме того, вы можете транспонировать матрицу B перед отправкой в функцию умножения. Таким образом, вы получите линейный доступ к элементам матрицы B. Чтобы объяснить вам больше, рассмотрим
A -------- and B | | | |
-------- | | | |
-------- | | | |
-------- | | | |
Здесь вы всегда будете учитывать, чтобы умножить первую строку A на первый столбец B. И, поскольку вы используете C
, я полагаю, ЦП требует дополнительных усилий для чтения всех столбцов матрицы B один за другим внутри памяти. Чтобы облегчить эти усилия, вы можете транспонировать матрицу и получить строки матрицы B'
(которые, по сути, являются не чем иным, как столбцами B
) и использовать мозаику цикла для кэширования максимального количества элементов для умножения. Надеюсь, это поможет.
person
Recker
schedule
11.10.2012