最快的方式通过2d数组传播c++
Fastest way to propgate through a 2d Array C++
我有2个大的2d数组,这是100 *100。它有一个大的循环来做几次运算。它里面有3个循环;第一个循环在arr1
中存储arr2
中每个单元格的和乘以数字,第二个循环将两个数组流式传输到文件中,第三个循环在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秒。我应该如何优化代码工作在最快的时间可能。
您可以使用第三个数组来临时存储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;
}
注意: OP的代码发生了巨大的变化,以响应关于填充等的评论。原来的代码并没有什么问题——这就是我给出这个答案的基础。
假设您的2D数组以row-major为索引(第一个索引是行,第二个索引是列),那么您的内存访问已经按照最佳缓存利用率的正确顺序进行了(您正在访问附近的元素)。您的最新代码将此假设称为问题,因为您似乎已将'maxi'重命名为'x',这表明您正在索引列主 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++) - 预取请求——一种特定于编译器/处理器的减少内存访问延迟的方法
- 确保在编译 时启用了优化
- 根据数组的大小,您可能会发现将算法列化以更好地利用可用的缓存 是有利的
充分利用可用的计算资源(非常依赖于平台):
- 创建基于simd的实现
- 充分利用你的多核CPU——OpenMP
- 充分利用你的GPU——OpenCL
相关文章:
- Mongodb c++驱动程序:如何查询元素的数组
- 将数组的地址分配给变量并删除
- 从C++本机插件更新Vector3数组
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 数组索引的值没有增加
- 将对象数组的引用传递给函数
- 为char数组调整zlib-zpipe
- 2D数组来自文本输入,中间有空格
- std::向量与传递值的动态数组
- 在c++中用vector填充一个简单的动态数组
- 使用strcpy将char数组的元素复制到另一个数组
- 使用指针从C++中的数组中获取最大值
- C++使用整数的压缩数组初始化对象
- 告诉一个 const char 数组,除了编译时 C 样式的字符串外,它不以 '