我正在尝试优化一些我编写的C代码,该代码将Matrix通过其转置进行乘法运算,并想知道是否有人可以看到我能做的其他事情,从而使我的方法在计算时间/时钟方面更加高效周期。
出于本示例的目的,我宁愿不更改算法以使其在数学上更有效-即在将Matrix与它的逆矩阵相乘时利用对角线属性。
我一直以一些示例代码为基础建立解决方案,然后从那里对其进行修改。到目前为止,我已经意识到我可以更改循环中事物的计算顺序,以避免不必要的计算。
未修改的示例代码:
void print_unmodified()
{
unsigned int n = 64;
unsigned int A[N_MAX]; // N_MAX = 64*64
unsigned int B[N_MAX];
// Initialising the A Matrix with values 1->64^2
for (int i = 0; i < (n * n); i++)
{
A[i] = i + 1;
}
// Initialising the B Matrix with zeros
for (int i = 0; i < (n * n); i++)
{
B[i] = 0;
}
// Matrix Multiplicaiton B = A*A'
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
for (int k = 0; k < n; k++)
{
B[i + n * j] = B[i + n * j] + A[i + n * k] * A[j + n * k];
}
}
}
}
我的修改代码:
void print_modified()
{
unsigned int n = 64;
unsigned int A[N_MAX];
unsigned int B[N_MAX];
unsigned int temp = 0;
// Initialising the A Matrix with values 1->64^2
for (int i = 0; i < (n * n); i++)
{
A[i] = i + 1;
}
// Matrix Multiplicaiton B = A*A'
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
temp = 0;
for (int k = 0; k < (n*n); k+=n)
{
temp += A[j + k] * A[i + k];
}
B[j + n*i] = temp;
}
}
}
这两种方法都以结果B矩阵结尾,所以我知道我当前的方法在数学上是正确的。
编辑:固定类型-我不想将A乘以它的倒数,而是将A与它的转置相乘。
答案 0 :(得分:0)
通过在同一A
循环中初始化B
和for
矩阵,可以改善第一个解决方案。
n * k
也会被计算两次,您可以将其存储到变量中以节省时间。
最好使用B[i + n * j] += ...
而不是B[i + n * j] = B[i + n * j] + ...
,因为在第一个中,B[i + n * j]
被读取一次,而在第二个被读取两次。
void print_unmodified()
{
unsigned int n = 64u;
unsigned int A[N_MAX];
unsigned int B[N_MAX];
/* Initializing the A and B matrix with values 1->64^2 */
for (int i = 0; i < (n * n); i++)
{
A[i] = i + 1;
B[i] = 0u;
}
/* Matrix Multiplication B = A*A' */
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
int index = i + n*j;
for (int k = 0; k < n; k++)
{
int p = n * k;
B[index] += A[i + p] * A[j + p];
}
}
}
}
答案 1 :(得分:0)
发布的代码给出了正确的答案,矩阵 B 是另一个矩阵 A 的转置乘积,但是两个矩阵都存储在两个数组中按照主要列的顺序(或至少是OP在评论中指出的内容)。
考虑以下代码段:
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
B[i + n * j] = B[i + n * j] + A[i + n * k] * A[j + n * k];
// ^^^^^^^^^ ^^^^^^^^^
}
}
}
我们可以注意到,内部循环每次都跳过n
元素遍历这些数组,这对缓存不友好。
如果我们安排循环的顺序,以使内部循环在连续的元素上进行迭代,则可以提高性能:
// Calculate the matrix B = A times A transposed. A is an n x n matrix.
// A and B are stored in plain arrays ('src' and 'dest') in column-major order
void mult_AAT(size_t n, value_t const *src, value_t *dest)
{
for (size_t i = 0, end = n * n; i < end; i++)
{
dest[i] = 0;
}
for (size_t k = 0; k < n; k++) // <--
{
for (size_t j = 0; j < n; j++) // <-
{
for (size_t i = 0; i < n; i++)
{
dest[j * n + i] += src[k * n + i] * src[k * n + j];
// ^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^
}
}
}
}
实时HERE。