C++ 基于矩阵转置的矩阵乘法优化

C++ 基于矩阵转置的矩阵乘法优化,c++,c,algorithm,optimization,matrix-multiplication,C++,C,Algorithm,Optimization,Matrix Multiplication,我正在处理一个赋值,在这个赋值中,我转置一个矩阵,以减少矩阵乘法运算的缓存未命中。从我从几个同学那里了解到,我应该有8倍的进步。然而,我只得到2倍。。。我可能做错了什么 void转置(整数大小,矩阵m){ int i,j; 对于(i=0;i ,C标题,而不是C++头。 由于您实现了结构矩阵,因此我对复制构造函数导致的速度缓慢的评论是不正确的。这是不正确的,更糟糕!将隐式定义的复制构造函数与包含裸指针的类或结构结合使用是在玩火。如果有人调用m(a,a,a_squared)来得到矩阵a的平方,你会

我正在处理一个赋值,在这个赋值中,我转置一个矩阵,以减少矩阵乘法运算的缓存未命中。从我从几个同学那里了解到,我应该有8倍的进步。然而,我只得到2倍。。。我可能做错了什么

void转置(整数大小,矩阵m){
int i,j;
对于(i=0;i
到目前为止,我做得对吗

仅供参考:我需要做的下一个优化是使用SIMD/Intel SSE3

到目前为止,我做得对吗

不,你的转置有问题。在开始担心性能之前,您应该看到这个问题。当您在进行任何类型的黑客攻击以进行优化时,最好使用幼稚但次优的实现作为测试。如果一个优化不能得到正确的答案,那么它的加速比达到100倍是毫无价值的

另一个有帮助的优化是通过引用传递。你在传递副本。事实上,您的
矩阵结果可能永远不会出来,因为您正在传递副本。再一次,你应该测试一下

另一个有助于加速的优化是缓存一些指针。这仍然相当缓慢:

for(k = 0; k < size; k++)
    tmp += a.element[i][k] * b.element[j][k];
result.element[i][j] = tmp;
for(k=0;k
优化器可能会找到解决指针问题的方法,但可能不会。如果不使用非标准的
\uuuuuuu restrict\uuuuu
关键字告诉编译器矩阵不重叠,至少不会。缓存指针,这样您就不必执行
a.element[i]
b.element[j]
result.element[i]
。告诉编译器这些数组不与
\uuuuuu restrict\uuuuu
关键字重叠可能还是有帮助的

附录
查看代码后,它需要帮助。首先是一个小评论。你不是在写C++。你的代码是C,带有一点C++的提示。您使用的是<代码>结构> <代码>,而不是<代码>类<代码> >代码> Malc 而不是<代码>新< /COD>,<代码> TyPufFrase,而不是“代码>结构> <代码>,C标题,而不是C++头。

由于您实现了
结构矩阵
,因此我对复制构造函数导致的速度缓慢的评论是不正确的。这是不正确的,更糟糕!将隐式定义的复制构造函数与包含裸指针的类或结构结合使用是在玩火。如果有人调用
m(a,a,a_squared)
来得到矩阵
a的平方,你会被严重烧伤。如果有人希望
m(a,a,a)
a
2进行就地计算,你会被烧坏得更厉害

从数学上讲,您的代码只涉及矩阵乘法问题的一小部分。如果有人想用100x1000矩阵乘以1000x200矩阵怎么办?这是完全正确的,但是您的代码不能处理它,因为您的代码只能处理平方矩阵。另一方面,您的代码将允许某人将100x100矩阵乘以200x200矩阵,这毫无意义


从结构上讲,您的代码几乎100%地保证,由于您使用的是不规则数组,因此它的速度会很慢
malloc
可以在内存中喷洒矩阵的行。如果矩阵在内部表示为一个连续数组,但被访问时就像它是一个NxM矩阵一样,那么您将获得更好的性能。C++提供了一些好的机制来完成这项工作。

如果你的任务暗示你必须转置,那么,当然,你应该纠正你的转置过程。目前,它做了两次转置,结果根本没有转置。不应读取j=循环

j=0; j<size; j++

j=0;j+1很好地解决了转置问题。我读过了。和@JoelLee一样,在catch上是+1:)嗯,我认为C/C++和所有低级内存的混淆是因为我通常不使用低级语言编程。。。我会试着读更多关于它的内容。。。重新考虑一下关于方阵的事情,我认为这是这个赋值的要求,但我会再次验证。关于你最后关于malloc分配非连续内存的评论。那么,如何使它连续?我也建议您考虑循环拼接的选项,以使两个矩阵的部分基本上被缓存,从而减少浮点运算的总执行时间。@ AbnnOOL -好的建议,但是当矩阵被表示为一个不规则数组时,这有点难做。使用
malloc
单独分配行。
j=0; j<size; j++
j=0; j<i; j++
  for (int i=0; i<size; i++)
  {
    for (int k=0; k<size; k++)
    {
      double tmp = a[i][k];
      for (int j=0; j<size; j++)
      {
        result[i][j] += tmp * b[k][j];
      }
    }
  }