Слово, которое вы ищете, это thrashing. Поиск умножения матриц в Google дает больше результатов.
Стандартный алгоритм умножения для c = a*b будет выглядеть так:
void multiply(double[,] a, double[,] b, double[,] c)
{
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
for (int k = 0; k < n; k++)
C[i, j] += a[i, k] * b[k, j];
}
По сути, быстрая навигация по памяти большими шагами отрицательно сказывается на производительности. Шаблон доступа для k в B[k, j] делает именно это. Таким образом, вместо того, чтобы прыгать по памяти, мы можем переставить операции так, чтобы самые внутренние циклы работали только со вторым индексом доступа к матрицам:
void multiply(double[,] a, double[,] B, double[,] c)
{
for (i = 0; i < n; i++)
{
double t = a[i, 0];
for (int j = 0; j < n; j++)
c[i, j] = t * b[0, j];
for (int k = 1; k < n; k++)
{
double s = 0;
for (int j = 0; j < n; j++ )
s += a[i, k] * b[k, j];
c[i, j] = s;
}
}
}
Это был пример, приведенный на этой странице. Однако другой вариант — заранее скопировать содержимое B[k, *] в массив и использовать этот массив во внутренних вычислениях цикла. Этот подход обычно намного быстрее, чем альтернативы, даже если он включает в себя копирование данных. Даже если это может показаться нелогичным, попробуйте сами.
void multiply(double[,] a, double[,] b, double[,] c)
{
double[] Bcolj = new double[n];
for (int j = 0; j < n; j++)
{
for (int k = 0; k < n; k++)
Bcolj[k] = b[k, j];
for (int i = 0; i < n; i++)
{
double s = 0;
for (int k = 0; k < n; k++)
s += a[i,k] * Bcolj[k];
c[j, i] = s;
}
}
}
person
Cesar
schedule
26.01.2013