Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
优化“四重嵌套”;至于;环 我在C++中开发了一个二维的数值模型,我想加快一个特定的成员函数,它减慢了我的代码。函数需要在模型中的每个i,j网格点上循环,然后在l和m上的每个网格点上执行双重求和。功能如下: int Class::Function(void) { double loadingEta; int i,j,l,m; //etaLatLen=64, etaLonLen=2*64 //l_max = 12 for (i=0; i<etaLatLen; i++) { for (j=0; j < etaLonLen; j++) { loadingEta = 0.0; for (l=0; l<l_max+1; l++) { for (m=0; m<=l; m++) { loadingEta += etaLegendreArray[i][l][m] * (SH_C[l][m]*etaCosMLon[j][m] + SH_S[l][m]*etaSinMLon[j][m]); } } etaNewArray[i][j] = loadingEta; } } return 1; } etaLegendreArray = new double**[etaLatLen]; for (int i=0; i<etaLatLen; i++) { etaLegendreArray[i] = new double*[l_max+1]; for (int l=0; l<l_max+1; l++) { etaLegendreArray[i][l] = new double[l_max+1]; } } SH_C = new double*[l_max+1]; SH_S = new double*[l_max+1]; for (int i=0; i<l_max+1; i++) { SH_C[i] = new double[l_max+1]; SH_S[i] = new double[l_max+1]; } etaCosMLon = new double*[etaLonLen]; etaSinMLon = new double*[etaLonLen]; for (int j=0; j<etaLonLen; j++) { etaCosMLon[j] = new double[l_max+1]; etaSinMLon[j] = new double[l_max+1]; } int类::函数(void){ 双负载ETA; int i,j,l,m; //标准具=64,标准具=2*64 //l_max=12 对于(i=0;i_C++_Performance_For Loop_Nested - Fatal编程技术网

优化“四重嵌套”;至于;环 我在C++中开发了一个二维的数值模型,我想加快一个特定的成员函数,它减慢了我的代码。函数需要在模型中的每个i,j网格点上循环,然后在l和m上的每个网格点上执行双重求和。功能如下: int Class::Function(void) { double loadingEta; int i,j,l,m; //etaLatLen=64, etaLonLen=2*64 //l_max = 12 for (i=0; i<etaLatLen; i++) { for (j=0; j < etaLonLen; j++) { loadingEta = 0.0; for (l=0; l<l_max+1; l++) { for (m=0; m<=l; m++) { loadingEta += etaLegendreArray[i][l][m] * (SH_C[l][m]*etaCosMLon[j][m] + SH_S[l][m]*etaSinMLon[j][m]); } } etaNewArray[i][j] = loadingEta; } } return 1; } etaLegendreArray = new double**[etaLatLen]; for (int i=0; i<etaLatLen; i++) { etaLegendreArray[i] = new double*[l_max+1]; for (int l=0; l<l_max+1; l++) { etaLegendreArray[i][l] = new double[l_max+1]; } } SH_C = new double*[l_max+1]; SH_S = new double*[l_max+1]; for (int i=0; i<l_max+1; i++) { SH_C[i] = new double[l_max+1]; SH_S[i] = new double[l_max+1]; } etaCosMLon = new double*[etaLonLen]; etaSinMLon = new double*[etaLonLen]; for (int j=0; j<etaLonLen; j++) { etaCosMLon[j] = new double[l_max+1]; etaSinMLon[j] = new double[l_max+1]; } int类::函数(void){ 双负载ETA; int i,j,l,m; //标准具=64,标准具=2*64 //l_max=12 对于(i=0;i

优化“四重嵌套”;至于;环 我在C++中开发了一个二维的数值模型,我想加快一个特定的成员函数,它减慢了我的代码。函数需要在模型中的每个i,j网格点上循环,然后在l和m上的每个网格点上执行双重求和。功能如下: int Class::Function(void) { double loadingEta; int i,j,l,m; //etaLatLen=64, etaLonLen=2*64 //l_max = 12 for (i=0; i<etaLatLen; i++) { for (j=0; j < etaLonLen; j++) { loadingEta = 0.0; for (l=0; l<l_max+1; l++) { for (m=0; m<=l; m++) { loadingEta += etaLegendreArray[i][l][m] * (SH_C[l][m]*etaCosMLon[j][m] + SH_S[l][m]*etaSinMLon[j][m]); } } etaNewArray[i][j] = loadingEta; } } return 1; } etaLegendreArray = new double**[etaLatLen]; for (int i=0; i<etaLatLen; i++) { etaLegendreArray[i] = new double*[l_max+1]; for (int l=0; l<l_max+1; l++) { etaLegendreArray[i][l] = new double[l_max+1]; } } SH_C = new double*[l_max+1]; SH_S = new double*[l_max+1]; for (int i=0; i<l_max+1; i++) { SH_C[i] = new double[l_max+1]; SH_S[i] = new double[l_max+1]; } etaCosMLon = new double*[etaLonLen]; etaSinMLon = new double*[etaLonLen]; for (int j=0; j<etaLonLen; j++) { etaCosMLon[j] = new double[l_max+1]; etaSinMLon[j] = new double[l_max+1]; } int类::函数(void){ 双负载ETA; int i,j,l,m; //标准具=64,标准具=2*64 //l_max=12 对于(i=0;i,c++,performance,for-loop,nested,C++,Performance,For Loop,Nested,,如果CPU支持它并且编译器进行了足够的优化,您可能会从(融合乘法-加法)函数中获得一些小的增益,以转换一些两步操作(乘法,然后加法)它还可以提高精度,因为对融合运算只进行一次浮点舍入,而不是对乘法和加法进行一次浮点舍入 假设我读对了,您可以将最内层循环的表达式更改为: loadingEta += etaLegendreArray[i][l][m] * (SH_C[l][m]*etaCosMLon[j][m] + SH_S[l][m]*etaSinMLon[j][m]); to(注意现在不使用

,如果CPU支持它并且编译器进行了足够的优化,您可能会从(融合乘法-加法)函数中获得一些小的增益,以转换一些两步操作(乘法,然后加法)它还可以提高精度,因为对融合运算只进行一次浮点舍入,而不是对乘法和加法进行一次浮点舍入

假设我读对了,您可以将最内层循环的表达式更改为:

loadingEta += etaLegendreArray[i][l][m] * (SH_C[l][m]*etaCosMLon[j][m] + SH_S[l][m]*etaSinMLon[j][m]);
to(注意现在不使用
+=
,它被合并到
fma
):

我不希望有什么神奇的性能方面的东西,但它可能会有一点帮助(同样,只有在优化足够让编译器内联硬件指令来完成这项工作的情况下;如果它调用库函数,您将失去对函数调用开销的任何改进).而且,通过避免两个四舍五入步骤,它应该会稍微提高精度

请注意,如果这是一个选项,我会同意,因为(如您所见)
fma
函数往往会降低代码的可读性

您的编译器也可能提供浮点指令的矢量化版本,这可能会有意义地提高性能(请参阅前面关于自动转换为FMA的链接)


大多数其他改进都需要更多关于目标、所用输入阵列的性质等的信息。简单的线程可能会给您带来一些好处,OpenMP pragmas可能是简化循环并行化的一种方法.

跳到这里的X-Y区域。与其加快算法,不如尝试加快数据访问速度

etaLegendreArray = new double**[etaLatLen];
for (int i=0; i<etaLatLen; i++) {
    etaLegendreArray[i] = new double*[l_max+1];
    for (int l=0; l<l_max+1; l++) {
        etaLegendreArray[i][l] = new double[l_max+1];
    }
}
这看起来不是您的情况,所以您要做的是分配一个1D数组,因为它将是一个连续的内存块

double * etaLegendreArray= new double [SIZE1*SIZE2*SIZE3];
并手动进行数组索引数学运算

etaLegendreArray[(x * SIZE2 + y) * SIZE3 + z] = data;
看起来这应该会更慢,因为有了所有额外的数学,是吗?事实证明,每次使用
[]
时,编译器都会对你隐藏看起来非常类似的数学。你几乎什么都没有损失,当然也不会像使用一个不必要的编译器那样损失那么多

但是到处重复这个数学是很疯狂的,早晚你会搞砸的,即使可读性的消耗没有让你首先想到死亡,所以你真的想把1D数组包装在一个类中来帮你处理这个数学。一旦你这样做了,你还不如让这个类来处理分配和释放因此,您可以利用。
new
s和
delete
s的
for
loops的
功能。所有功能都用蝴蝶结包裹和捆绑


这将以一种可预测且缓存友好的方式解决您可能需要的基本功能。

更改循环顺序不会降低复杂性。如果您想真正加快速度,您可能希望在多个进程或线程之间分配工作,但这也会带来开销。您的数组是如何定义的?哟u可能能够提高数据的缓存能力。听起来像是在2D网格上传递2D过滤器。因此,使用KissFFT、卷积变换到频域,然后转换回空域。感谢您的回复。我添加了有关如何将阵列分配到post的代码。可能还值得一提的是pitf浮点数求和涉及的所有值(即:排序,以便首先求和最小值)。取决于体系结构(即:嵌入式),如果整数运算速度明显加快,那么使用定点规范化/求和也可能是值得的。有趣的是,我不知道FMA。我是用g++6编译的,所以我会看看FMA是否是内置优化的一部分。谢谢!
double * etaLegendreArray= new double [SIZE1*SIZE2*SIZE3];
etaLegendreArray[(x * SIZE2 + y) * SIZE3 + z] = data;