我有两个大小相同的数组:
A = [a1, a2, a3]
B = [b1; b2; b3]
我需要执行数组乘法才能构建以下矩阵:
|a1|
M = A * B = |a2| * |b1 b2 b3| //M31 * M13 ==> M33 and M13 * M31 ==> M11. Mnk: Matrix with n lines and k columns.
|a3|
| a1b1 a1b2 a1b3 |
M = | a2b1 a2b2 a2b3 |
| a3b1 a3b2 a3b3 |
哪个是执行此任务的最快算法?
更详细:我需要使用8086指令集完成这项工作,但在这里我更喜欢用C代码接收算法。
答案 0 :(得分:1)
了解BLAS和LAPACK。这些都是高度优化的。除非你有理由避免使用库,否则不要重新发明轮子。这两个都有C API。
答案 1 :(得分:1)
看起来像Matrix Multiplication Algorithm 更确切地说,我认为您正在寻找efficient方式。
多重矩阵的一般方法是O(n ^ 3),但是以有效的方式,你将得到O(n ^ 2.807)。是否值得花时间实施有效的方式?我不知道,但你必须对它进行评估。
如果你只有1D数组,那么唯一的方法是双循环,在这种情况下,你看的是运行时间O(n ^ 2)。 想出来应该不会那么复杂:
for(int i = 0; i < A.length; i++)
{
for(int j = 0; j < B.length; j++)
{
C[i][j] = A[i] * B[j];
}
}
答案 2 :(得分:1)
对于这种简单的3x3情况和编译器优化,最简单的O(N^2)
算法可能足够快。如果有人想要进行基准测试,那么非常欢迎您:
#include <stdio.h>
void lean_and_mean_mul(int a[3], int b[3], int out[3][3])
{
int i, j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
out[i][j] = a[i] * b[j];
}
}
}
int main(void)
{
int a[] = { 1, 2, 3 };
int b[] = { 4, 5, 6 };
int out[3][3];
lean_and_mean_mul(a, b, out);
int i, j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
printf("%d ", out[i][j]);
}
printf("\n");
}
return 0;
}
让我们看看lean_and_mean_mul()
生成的gcc -O2 -S
的汇编:
xorl %eax, %eax
.L2:
movl (%rsi), %ecx
imull (%rdi), %ecx
movl %ecx, (%rdx,%rax)
movl 4(%rsi), %ecx
imull (%rdi), %ecx
movl %ecx, 4(%rdx,%rax)
movl 8(%rsi), %ecx
imull (%rdi), %ecx
addq $4, %rdi
movl %ecx, 8(%rdx,%rax)
addq $12, %rax
cmpq $36, %rax
jne .L2
rep
ret
请注意,编译器决定unroll一个循环。
使用gcc -O3
编译器展开两个循环。 Code。它真的很快,因为它根本没有跳跃。
答案 3 :(得分:0)
如果您的数组很大并且想要尽可能快地将它们相乘,那么您应该查看BLAS库。
答案 4 :(得分:0)
我建议你以最简单/最简单的方式编写代码(使用2个fors和if / else),以便让编译器决定哪些优化可以/不可以完成(不要忘记设置标志到-O3)。这比通过反转矩阵访问等来尝试优化缓存/内存访问来尝试优化代码要好。如果你想进行真正的优化,找一个更好的算法,否则编码很简单。
答案 5 :(得分:0)
Wikipedia article on Matrix Multiplication告诉您所需的一切。
在这种情况下,你不会比 O(n ^ 2) 更快。
在一般情况下,矩阵乘法的最佳性能是 O(n ^ log2(7))
(大约 O(n ^ 2.8) )