关于网友提出的“ 优化代码,欢迎高手支招。”问题疑问,本网通过在网上对“ 优化代码,欢迎高手支招。”有关的相关答案进行了整理,供用户进行参考,详细问题解答如下:
问题: 优化代码,欢迎高手支招。
描述:本帖最后由 ganpengjin1 于 2014-08-31 22:02:19 编辑
typedef struct cVector{
float cVector[3];
} VectorTag;
float getData(VectorTag &r_vector) {
float len = 0;
for(int i =0; i < 3; ++i) {
len += pow(r_vector.cVector[i], 2);
}
len = sqrt(len);
for(int i = 0; i < 3; ++i) {
r_vector.cVector[i] /= len;
}
return len;
}

解决方案1:
我测试了下,下面是测试的结果:

下面是我的测试代码:
#include
#include
using namespace std ;
bool g_bSSE = false ;
typedef struct Vector{
float cVector[3];
} VectorTag;
float getData_Fast(VectorTag &r_vector)
{
float len = 0 ;
if(g_bSSE == false)
{
len = sqrt(r_vector.cVector[0] * r_vector.cVector[0] +
r_vector.cVector[1] * r_vector.cVector[1] +
r_vector.cVector[2] * r_vector.cVector[2]);
r_vector.cVector[0] = r_vector.cVector[0] * (1 / len);
r_vector.cVector[1] = r_vector.cVector[1] * (1 / len);
r_vector.cVector[2] = r_vector.cVector[2] * (1 / len);
}
else
{
VectorTag *pVector = &r_vector ;
_asm
{
mov esi , pVector ; copy the pointer of this to esi
movups xmm0, [esi] ; copy the this vector to xmm0
movaps xmm2, xmm0
mulps xmm0, xmm0 ; multiply all the component
movaps xmm1, xmm0 ; copy result to xmm1
shufps xmm1, xmm1, 4Eh; shuffle : f1, f0, f3, f2
addps xmm0, xmm1 ;
movaps xmm1, xmm0 ; copy the xmm0 to xmm1
shufps xmm1, xmm1, 11h;
addps xmm0, xmm1
rsqrtps xmm0, xmm0 ;
mulps xmm2, xmm0 ; multiply the inverse of squre root
movups [esi], xmm2
}// end for _asm
}
return len;
}
int main()
{
LARGE_INTEGER nLastTime, nTime;
VectorTag u;
u.cVector[0] = 1.0f; u.cVector[1] = 1.0f ;
u.cVector[2] = 1.0f ;
g_bSSE = true ;
QueryPerformanceCounter(&nLastTime);
getData_Fast(u);
QueryPerformanceCounter(&nTime);
cout << "With SSE:" << nTime.QuadPart - nLastTime.QuadPart << endl ;
VectorTag v;
v.cVector[0] = 1.0f; v.cVector[1] = 1.0f ;
v.cVector[2] = 1.0f ;
g_bSSE = false ;
QueryPerformanceCounter(&nLastTime);
getData_Fast(v);
QueryPerformanceCounter(&nTime);
cout << "Without SSE:" << nTime.QuadPart - nLastTime.QuadPart << endl ;
system("cmd");
return 0 ;
}
您看看,是不是我的测试代码有问题???我用的是VS2010
解决方案2: 这个是向量的Normalize操作,可以使用SIMD指令来进行优化操作。逻辑上也可以使用其他的近似算法来替代完全的数学上定义的Normalize操作。
参考文章:http://blog.csdn.net/i_dovelemon/article/details/38870933
解决方案3: 编译器的代码优化有很多奥妙,比如这个版本:
float getData_Fast(VectorTag &r_vector)
{
float len = sqrt(r_vector.cVector[0] * r_vector.cVector[0] +
r_vector.cVector[1] * r_vector.cVector[1] +
r_vector.cVector[2] * r_vector.cVector[2]);
r_vector.cVector[0] = r_vector.cVector[0] * (1 / len);
r_vector.cVector[1] = r_vector.cVector[1] * (1 / len);
r_vector.cVector[2] = r_vector.cVector[2] * (1 / len);
return len;
}
看起来不咋地,但是icc、msvc、gcc都可以把它优化得更快,只有bcc是一个例外(不过目前bcc的优化能力已经沦落到二流水平,可以不予考虑)。
解决方案4:精度不够,精度要上去,迭代次数就要多,速度优势就没了。实际上这个算法早就没有速度优势了,SSE中的rsqrtss指令只要5个时钟周期(源操作数在寄存器中)或者7个时钟周期(源操作数在内存中)。
嗯,可以考虑直接实现f(x)=x^(-0.5)
解决方案5:雷神之锤,快速求平方根的倒数,基于浮点数的二进制表示,初始化一个较精确的估计值
精度不够,精度要上去,迭代次数就要多,速度优势就没了。实际上这个算法早就没有速度优势了,SSE中的rsqrtss指令只要5个时钟周期(源操作数在寄存器中)或者7个时钟周期(源操作数在内存中)。
解决方案6: 这个代码优化的余地不大,如果用icc或者msvc 2013编译C代码,性能已经很好了,内联的话并不逊于手工SSE优化的代码,使用SSE指令还得把float cVector[3];定义改成float cVector[4];。
4楼和6楼的代码都可以,只不过4楼的代码有一点小错误,return len;要改成return 1/len;。
解决方案7: 都是牛人, = =
解决方案8: 用icc做自动矢量化编译,VC++ 2013也可以,但是效果要差一些。
解决方案9: 如果是用在图像处理中处理像素的过程,那么最简单的优化就是尽量不使用除法或者开方(网上可以找到这类用乘法替换的优化代码),或者设置编译器使用SSE, SIMD指令。
解决方案10:const int Table_Pow[] = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81};
typedef struct
{
int cVector[3];
}VectorTag;
float getData(VectorTag& r_vector)
{
float len = 0.0;
for (int i=0; i<3; ++i)
{
if (r_vector.cVector[i] >= 0)
{
len += Table_Pow[r_vector.cVector[i]];
}
else
{
len -= Table_Pow[r_vector.cVector[i]];
}
}
len = sqrt(len);
for (int i=0; i<3; ++i)
{
if (r_vector.cVector[i] < len)
{
r_vector.cVector[i] = 0;
}
else
{
r_vector.cVector[i] /= len;
}
}
return len;
}
脑短了。。想成把int看成个位数了
解决方案11: 嗯。楼上Idle_的精度更高。
float getData(VectorTag &r_vector) {
int* x = &r_vector.cVector[0];
long long a1 = x[0], a2 = x[1], a3 = x[2];
float len = sqrt(float(a1 * a1 + a2 * a2 + a3 * a3));
x[0] = int(x[0] / len + 0.5f);
x[1] = int(x[1] / len + 0.5f);
x[2] = int(x[2] / len + 0.5f);
return len;
}
解决方案12:
float getData(VectorTag & r_vector)
{
float len = sqrt(pow(r_vector.cVector[0], 2.0f)
+ pow(r_vector.cVector[1], 2.0f)
+ pow(r_vector.cVector[2], 2.0f));
r_vector.cVector[0] /= len;
r_vector.cVector[1] /= len;
r_vector.cVector[2] /= len;
return len;
}
至于数学上的优化。。。自己再想想吧。。。
解决方案13: 是指这种优化吗?
float getData(VectorTag &r_vector) {
int* x = &r_vector.cVector[0];
float len = 1/sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]);
x[0] *= len;
x[1] *= len;
x[2] *= len;
return len;
}
解决方案14:const int Table_Pow[] = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81};
typedef struct
{
int cVector[3];
}VectorTag;
float getData(VectorTag& r_vector)
{
float len = 0.0;
for (int i=0; i<3; ++i)
{
if (r_vector.cVector[i] >= 0)
{
len += Table_Pow[r_vector.cVector[i]];
}
else
{
len -= Table_Pow[r_vector.cVector[i]];
}
}
len = sqrt(len);
for (int i=0; i<3; ++i)
{
if (r_vector.cVector[i] < len)
{
r_vector.cVector[i] = 0;
}
else
{
r_vector.cVector[i] /= len;
}
}
return len;
}
解决方案15:
float (&v)[3] = _vector.cVector; //名字太长了,建立短连接, 呵呵
这都算?那我也加一个,auto& v = r_vector.vector;
不是, 23L代码敲错了, 修正一下而已。
解决方案16:float (&v)[3] = _vector.cVector; //名字太长了,建立短连接, 呵呵
这都算?那我也加一个,auto& v = r_vector.vector;
解决方案17: float (&v)[3] = _vector.cVector; //名字太长了,建立短连接, 呵呵
解决方案18: 去掉pow(x,2) --> x * x, 展开循环, 其他就留给编译器优化吧。
typedef struct cVector{
float cVector[3];
} VectorTag;
float getData(VectorTag &r_vector) {
float (&v)[3] = r_vector._vector.cVector; //名字太长了,建立短连接, 呵呵
float len = sqrt( v[0] * v[0] + v[1]*v[1] + v[2]*v[2]);
v[0] /= len; v[1] /= len; v[2]/len;
return len;
}
解决方案19: 查表最快。。。空间换时间。。。
解决方案20: 一看就是把向量normalize的操作。这正常没啥好办法,就正常做就行。不过lz又是int又是用pow函数,也是醉了。
解决方案21: 既然楼主要速度,就上这个呗 http://en.wikipedia.org/wiki/Fast_inverse_square_root。
不优化 sqrt 和除法,光盯着其他,不成打酱油吗。
解决方案22: 你确认是int cVector[3]; 而不是float类型么?
否则3个正整数都比len小,求的结果必然都是0啊。
以上介绍了“ 优化代码,欢迎高手支招。”的问题解答,希望对有需要的网友有所帮助。
本文网址链接:http://www.codes51.com/itwd/3637169.html