我有2个大的2d阵列,这是100s * 100s。它有一个很大的循环来做几次操作。里面有3个循环; arr1
中第一个循环存储arr2
中每个单元格的总和乘以数字,第二个循环流将2个数组流式传输到一个文件,第三个循环存储在arr2
两个数组之和除以数字。
代码解释得更好:
for(int i=1;i<x+1;i++) {//initialize
for(int j=1;j<y+1;j++) {
arr1[i][j]=i*j*5.5;
arr2[i][j]=0.;
}
}
for (int i=0;i<x+2;i++) {//padding
vi[i][0]=5;
vi[i][y+1]=-5;
}
for (int j=0;j<y+2;j++) {//padding
vi[0][j]=10.;
vi[x+1][j]=-10.;
}
for(int t=0;t<times;++t) {
for(int i=1;i<x+1;++i) {
for(int j=1;j<y+1;j++) {
arr2[i][j]=(arr1[i+1][j]+arr1[i-1][j]+arr1[i][j-1]+arr1[i][j+1])*1.5;
}
}
arr2[1][1]=arr2[1][y]=arr2[x][1]=arr2[x][y]=0.;
for(int i=1;i<x+1;++i) {
for(int j=1;j<y+1;j++) {
arr1[i][j]=(arr1[i][j]+arr2[i][j])*0.5;
if(arr2[i][j]+arr1[i][j]>5.)
cout<<"\n"<<t<<" "<<i-1<<" "<<j-1<<" "<<arr1[i][j]<<" "<<arr2[i][j];
}
}
}
整个代码的工作时间超过14秒。我应该如何优化代码以尽可能快地工作。
答案 0 :(得分:1)
您可以使用第3个数组临时存储arr2的数组值以供下次运行。 完成第一个循环后,用临时数组覆盖arr2 - 就像这样你不需要第二个循环。你将节省一半的时间。
for (n=0;n<x;n++)
{
for (i=0;i<maxi;i++)
{
for (j=0;j<maxj;j++)
{
arr1[i][j]=(arr2[i+1][j]+arr2[i-1][j]+arr2[i][j+1]+arr2[i][j-1])*1.5;
arr_tmp[i][j] = (arr1[i][j]+arr2[i][j])*0.5;
}
}
arr2 = arr_tmp;
}
答案 1 :(得分:1)
注意: OP的代码在响应有关填充等的评论时发生了巨大变化。原始代码并没有什么问题 - 这就是我根据这个答案所做的。
假设您的2D数组已编入索引 row-major (第一个索引是行,第二个索引是列),您的内存访问的顺序已经正确,以获得最佳缓存利用率(随着进度,您将访问附近的元素)。您的最新代码会对此假设提出质疑,因为您似乎已将其重命名为“maxi&#39;成为&#39; x&#39;这表明你正在索引一个 column-major 2D数组(这对于C / C ++非常不标准)。
没有详细说明你如何声明你的2D数组,这可能会有所不同,但是通过将你的实现转换为使用原始指针,我获得了很大的改进。我还通过组合操作和交替每次迭代的方向来消除第二个循环(来自原始帖子)。我更改了加权系数,使它们加起来为1.0,这样我就可以更容易地测试它(通过生成图像输出)。
typedef std::vector< std::vector<double> > Array2D;
void run( int x, Array2D & arr2 )
{
Array2D temp = arr2; // easy way to create temporary array of the correct size
int maxi=arr2.size(), maxj=arr2[0].size();
for (int n=0;n<x;n++)
{
Array2D const & src = (n&1)?temp:arr2; // alternate direction
Array2D & dst = (n&1)?arr2:temp;
for (int i=1;i<maxi-1;i++)
{
double const * sp0=&src[i-1][1], * sp1=&src[i][1], * sp2=&src[i+1][1];
double * dp=&dst[i][1];
for (int j=1;j<maxj-1;j++)
{
dp[0]=(sp0[0]+sp1[-1]+4*sp1[0]+sp1[+1]+sp2[0])*0.125;
dp++, sp0++, sp1++, sp2++;
}
}
}
if ( (x&1) ) arr2=temp; // copy the result back if the iteration count was odd
} /**/
你可以研究的其他事情(有点依赖于平台):
restrict
关键字(非标准C ++)利用可用的计算资源(非常依赖于平台):