由于程序可能需要进行复杂的矩阵计算(上千维的矩阵乘法),在用普通的c++代码来跑的时候,耗时无法接受。在matlab上尝试同样的计算,快很多。 请问在算法相同的前提下,是否有办法大幅度提高运算速度。现在尝试尽量避免调用子函数,比如以前取数用GetElement,现在直接把GetElement里的代码放在乘法运算里,的确能快很多。但是还是无法达到满意的速度。 想请问一下是不是因为c++语言的原因导致的计算速度的不足,如果矩阵乘法运算直接用汇编写,然后在vc里调,不知道是不是会有提升?
调试欢乐多
汇编速度>C>C++>vc(vc写的c++程序已经没有标准c++的效率了)另外就是内存的管理,STL运用不好 会极大的降低运行速度
matlab就是C++写的吧
然后
这种数值计算最好上Fortran
最后
既然matlab快可以把matlab的m文件打包成C++的dll么
2. 采用多线程的方式
3.优化算法,如将矩阵分块
如果你的C/C++比MATLAB还慢,好好分析一下你的程序吧。真正想解决这类问题的方案是GPGPU, CUDA可以用,但是怕将来英伟达发展不长远。微软的Direct Compute已经能用了,目前双精度浮点运算还有一点问题。GPU特别适合你这种矩阵变换类计算,一个好一点的显卡可以将性能提高几十到上百倍。
还有一个方案是多核,OpenMP在VS2005以后就加上了,现在已经算比较成熟。把计算机的几个核心都开起来性能提高个一两倍还是比较可行的。
CMatrix CMatrix::operator*(const CMatrix& other) const
{
ASSERT (m_nNumColumns == other.GetNumRows());
CMatrix result(m_nNumRows, other.GetNumColumns());
double value; for (int i = 1 ; i <= result.GetNumRows(); ++i)
{
for (int j = 1 ; j <= other.GetNumColumns(); ++j)
{
value = 0.0 ;
for (int k = 1 ; k <= m_nNumColumns; ++k)
{
value += GetElement(i, k) * other.GetElement(k, j);
}
result.SetElement(i, j, value);
}
}
return result;
}
改用下面这段后,效率提高了些,但还是远远慢于matlab:
ASSERT(m_nNumColumns == other.GetNumRows()); // construct the object we are going to return
CMatrix mtxRet(m_nNumRows, other.GetNumColumns()); int i,j,k;
int pos1=0,pos2=0,pos3=0;
for (i = 0 ; i <mtxRet.m_nNumRows ; ++i)
{ for ( j = 0 ; j < mtxRet.m_nNumColumns; ++j)
{
pos2=0;
for (k = 0 ; k < other.m_nNumRows; ++k)
{
mtxRet.m_pData[j + pos1] += (this->m_pData[k + pos3])* (other.m_pData[j + pos2]);
pos2 +=other.m_nNumColumns;
}
} pos1 += mtxRet.m_nNumColumns;
pos3 +=this->m_nNumColumns;
}
return mtxRet ;
3000*3000的,matlab是十毫秒级,这段程序也是秒级的。 效率差距还是很大的。
说matlab慢的,先动手做做实验,看看吧
3000*3000 的,matlab是十毫秒级,这段程序也是秒级的。 效率差距还是很大的。是 matlab 内部有另外的算法。这是别人的程序员做了相当长的工作。换个说法,你就是用汇编也没人家的快。唯一可以做到的就是作弊(查表)。例如 x=1000+999+...+1; y= 2000+1999+...+1.求x+y=?;如果它保存有10000+9999+...+1的所有的结果,那么 x+y的值别人就查表求和就行。而你却是在for这么多次,永远不会比它快。我认为这不是代码效率的问题。是别人花了大量的初始工作,有更好的算法,而你的算法也许永远也不可能有别人快。不要在这浪费时间比较了,这不是代码问题。
矩阵相乘有特别的快速算法,你可以查查斯特拉森方法等。还有,在多重循环内部任何一点额外开销都会显著影响效率,你那么多的间接寻址在内循环也有很大的浪费。
加OpenMP的#pragma omp 吧,如果你是多核的电脑。