显然,转置矩阵然后乘以它比仅将两个矩阵相乘要快。但是,我的代码现在没有这样做,我也不知道为什么...(正常的乘法只是三重嵌套循环,它给了我大约1.12秒的时间来乘以1000x1000矩阵,而这段代码给了我8时间(慢而不是快)倍...我迷失了,任何帮助将不胜感激!:D
A = malloc (size*size * sizeof (double));
B = malloc (size*size * sizeof (double));
C = malloc (size*size * sizeof (double));
/* initialise array elements */
for (row = 0; row < size; row++){
for (col = 0; col < size; col++){
A[size * row + col] = rand();
B[size * row + col] = rand();
}
}
t1 = getTime();
/ *要测量的代码在这里* /
T = malloc (size*size * sizeof(double));
for(i = 0; i < size; ++i) {
for(j = 0; j <= i ; ++j) {
T[size * i + j] = B[size * j + i];
}
}
for (j = 0; j < size; ++j) {
for (k = 0; k < size; ++k) {
for (m = 0; m < size; ++m) {
C[size * j + k] = A[size * j + k] * T[size * m + k];
}
}
}
t2 = getTime();
最佳答案
我看到几个问题。
您只是设置C[size * j + k]
的值,而不是增加它。即使这是计算中的错误,也不应影响性能。另外,您需要在最内层循环开始之前将C[size * j + k]
初始化为0.0
。否则,您将增加一个未初始化的值。这是一个严重的问题,可能导致溢出。
乘法项是错误的。
请记住,您的乘法项需要表示:
C[j, k] += A[j, m] * B[m, k], which is
C[j, k] += A[j, m] * T[k, m]
代替
C[size * j + k] = A[size * j + k] * T[size * m + k];
你需要
C[size * j + k] += A[size * j + m] * T[size * k + m];
// ^ ^ ^^^^^^^^^^^^^^^^
// | | Need to get T[k, m], not T[m, k]
// | ^^^^^^^^^^^^^^^^
// | Need to get A[j, m], not A[j, k]
// ^^^^ Increment, not set.
我认为损害性能的主要原因除了错误之外,还在于您使用
T[size * m + k]
。当您这样做时,会有很多内存跳跃(m
是循环中变化最快的变量)来获取数据。当您使用正确的术语T[size * k + m]
时,将会少一些,并且应该会看到性能的提高。总之,使用:
for (j = 0; j < size; ++j) {
for (k = 0; k < size; ++k) {
C[size * j + k] = 0.0;
for (m = 0; m < size; ++m) {
C[size * j + k] += A[size * j + m] * T[size * k + m];
}
}
}
通过使用以下命令,您可能会获得更多性能:
double* a = NULL;
double* c = NULL;
double* t = NULL;
for (j = 0; j < size; ++j) {
a = A + (size*j);
c = C + (size*j);
for (k = 0; k < size; ++k) {
t = T + size*k;
c[k] = 0.0;
for (m = 0; m < size; ++m) {
c[k] += a[m] * t[m];
}
}
}
PS我还没有测试代码。只是给你一些想法。
关于c - 乘以大方阵的转置要比仅乘大方阵的速度慢…如何解决?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26353988/