我正在尝试提高算法速度,所以我使用“Instruments”为iOS运行我的应用程序,结果,几乎75%的时间用于将计算保存在向量中。
有没有人知道更好的方法来保存数据而不消耗如此大量的CPU?我想与访问缓存内存或类似的东西有关。该行标有注释,在此行中保存为短裤阵列中的短片。
short XY[32*32*2]
Mat _XY(bh, bw, CV_16SC2, XY), matA;
Mat dpart(dst, Rect(x, y, bw, bh));
for( y1 = 0; y1 < bh; y1++ )
{
short* xy = XY + y1*bw*2;
int X0 = M[0]*x + M[1]*(y + y1) + M[2];
int Y0 = M[3]*x + M[4]*(y + y1) + M[5];
float W0 = M[6]*x + M[7]*(y + y1) + M[8];
M2[2] = X0;
M2[3] = Y0;
for(x1=0; x1<bw; x1++)
{
float W = W0 + M[6]*x1;
W = 1./W;
float x12[2] = {x1*W,W};
matvec2_c(M2,x12,M3);
short aux = (M3[0]);
int aux2 = x1*2;
xy[aux2] = aux; // %60 CPU TIME
xy[x1*2+1] = (M3[1]); // 11% CPU TIME
}
// ...
}
void matvec2_c(float m[4], float v[2], float d[2])
{
d[0] = m[0]*v[0] + m[2]*v[1];
d[1] = m[1]*v[0] + m[3]*v[1];
}
答案 0 :(得分:1)
我的猜测是它是一个编译器优化问题:xy的指针计算是在for(x1 = -loop而不是for(y1 = -loop)中完成的,所以它完成的次数超过了必要的次数
可能的解决方案:使用assert()
强制实例化:
#include <assert.h>
...
short* xy = XY + y1*bw*2;
assert (xy!=NULL);
...
答案 1 :(得分:0)
我不确定你的代码是做什么的,它并不是真正的写作维护者友好。但是,如果您要在所有方向(左,上,右,下)访问这些阵列中的数据,那么以下内容可能适合您。
使用 Morton Code / Z order curve. 为您的数组编制索引。它增加了locality of reference,当您完全访问元素周围的元素时,它会提供更好的缓存行为。
考虑一下:使用经典的2d索引,到顶部和底部邻居的距离是间距或宽度。如果您的宽度/间距非常高,那么您将访问阵列中非常遥远的元素。考虑到CPU进行了大量的推测性缓存,很多这些推测导致了浪费的努力(所谓的cache-miss)。你有一些好的指数(左右邻居),还有一些非常非常糟糕的(顶部和底部邻居)。
使用莫顿索引,你没有理想的左/右邻居,但同样地,你没有遥远的上/下邻居。
如果平均而言, 点击缓存数据,那么访问这些数据非常便宜(在您开始访问之前,数据可能已经在缓存中了,感谢[http:// zh_cn] .wikipedia.org / wiki / Speculative_execution](推测性执行)和prefetching。
当然,如果您的大多数代码按从左到右的顺序访问元素,或者这不是相关的瓶颈,您可能不希望这样做。
答案 2 :(得分:0)
这是我能做到的最好的事情:
short XY[32*32*2];
int XYI[32*32*2];
Mat _XY(bh, bw, CV_16SC2, XY), matA;
Mat _XYI(bh, bw, CV_32S, XYI);
Mat dpart(dst, Rect(x, y, bw, bh));
for( y1 = 0; y1 < bh; y1++ )
{
int * xyi = XYI + y1*bw;
short * xy = XY + y1*bw*2;
int X0 = M[0]*x + M[1]*(y + y1) + M[2];
int Y0 = M[3]*x + M[4]*(y + y1) + M[5];
float W0 = M[6]*x + M[7]*(y + y1) + M[8];
M2[2]=X0;
M2[3]=Y0;
for(x1=0;x1<bw;x1++){
float W = W0 + M[6]*x1;
W= 1./W;
float x12[2]={x1*W,W};
matvec2_c(M2,x12,M3);
xyi[x1*2] = (M3[0]);//9%
xyi[x1*2+1]=(M3[1]);//6%
}
for(x1=0;x1<bw;x1++){
xy[x1*2] = xyi[x1*2];//4%
xy[x1*2+1]=xyi[x1*2+1];//3%
}
我只是将代码保存方程的部分拆分为两部分,所以我认为它与cpu访问缓存的方式或者与不同格式相关的东西有关。 算法时间从93毫秒减少到78毫秒。