Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.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
Arrays Fortran ndarray与n*1d阵列的效率比较_Arrays_Fortran_Hpc - Fatal编程技术网

Arrays Fortran ndarray与n*1d阵列的效率比较

Arrays Fortran ndarray与n*1d阵列的效率比较,arrays,fortran,hpc,Arrays,Fortran,Hpc,自从我开始编写我现在正在使用的实际代码以来,我一直在努力解决这个问题。 我的顾问在过去的十年里写了这篇文章,并且在某个时候,我们通常存储在矩阵或张量中的股票价值 实际上,我们看一看由维里定理(分子动力学模拟)计算出的六个独立分量的矩阵,他习惯于在每个记录的步骤中存储6*1D数组,每个值一个,即xy(n),xz(n)yz(n)。。。n是记录数 我假设单个数组s(n,3,3)可能更有效,因为值将彼此存储得更近(xy(n)和xz(n)没有理由在内存中并排存储),并且与损坏的内存或错误的内存访问相关的错

自从我开始编写我现在正在使用的实际代码以来,我一直在努力解决这个问题。 我的顾问在过去的十年里写了这篇文章,并且在某个时候,我们通常存储在矩阵或张量中的股票价值

实际上,我们看一看由维里定理(分子动力学模拟)计算出的六个独立分量的矩阵,他习惯于在每个记录的步骤中存储6*1D数组,每个值一个,即xy(n),xz(n)yz(n)。。。n是记录数

我假设单个数组s(n,3,3)可能更有效,因为值将彼此存储得更近(xy(n)和xz(n)没有理由在内存中并排存储),并且与损坏的内存或错误的内存访问相关的错误更少。我试图在实验室里讨论这个问题,但最终没人关心,再说一遍,这只是一个假设

如果代码中的所有内容都不是这样存储的话,我就不会被打扰了。每个3d数量都存储在3个不同的数组中,而不是1个数组,这让我觉得代码的性能很奇怪


对于长时间的计算和大数据量,它们是否有类似的效果?我决定在解决了由于错误的内存访问而导致的错误后在这里发布,因为我发现代码更可读,数据更容易计算(例如,s=s+…而不是xy=xy+…的六行).

假设您总是沿着
n
循环,并且在每个循环中需要访问矩阵中的所有组件,将数组存储为
s(6,n)
s(3,3,n)
将从中受益

但是,如果您的内部循环如下所示

resultarray(i)=xx(i)+yy(i)+zz(i)+2*(xy(i)+yz(i)+xz(i))

不要更改阵列布局,因为您可能会破坏优化。

假设您总是沿着
n
循环,并且在每个循环中需要访问矩阵中的所有组件,将阵列存储为
s(6,n)
s(3,3,n)
将从中受益

但是,如果您的内部循环如下所示

resultarray(i)=xx(i)+yy(i)+zz(i)+2*(xy(i)+yz(i)+xz(i))

不要更改阵列布局,因为可能会破坏优化。

列彼此靠近这一事实并不重要,尤其是在前导维度
n
较大的情况下。您的CPU有多个预取流,可以在不同列的不同阵列中同时预取

如果在数组
A(n,3,3)
中进行一些随机访问,其中
A
是可分配的,那么在编译时维度是未知的。因此,随机元素
a(i,j,k)
的地址将是(a(1,1,1))+i+(j-1)*n+(k-1)*3*n的
地址,并且必须在每次随机访问数组时计算它。地址的计算包括3次整数乘法(每次3个CPU周期)和至少3次加法(每次1个周期)。但是,编译器可以使用相对地址优化常规访问(可预测)

如果您有不同的1索引数组,则地址的计算只涉及一个整数加法(1个周期),因此,在使用单个3索引数组时,每次访问的性能损失至少为11个周期

此外,如果您有9个不同的数组,那么它们中的每一个都可以在缓存线边界上对齐,而您将被迫在行尾使用填充来确保单个数组的这种行为

因此我想说的是,在
A(n,3,3)
的特殊情况下,由于最后两个索引很小,并且在编译时已知,因此可以安全地将其转换为9个不同的数组,以潜在地获得一些性能


请注意,如果您经常以随机顺序使用同一索引
i
中9个数组的数据,则将数据重新组织为
a(3,3,n)
将显著提高性能。如果a是双精度的,
a(4,4,n)
如果在64字节边界上对齐,则会更好,因为每个
a(1,1,i)
将位于缓存线的第一个位置。

列彼此靠近这一事实不是很重要,特别是在前导维度
n
较大的情况下。您的CPU有多个预取流,可以在不同列的不同阵列中同时预取

如果在数组
A(n,3,3)
中进行一些随机访问,其中
A
是可分配的,那么在编译时维度是未知的。因此,随机元素
a(i,j,k)
的地址将是(a(1,1,1))+i+(j-1)*n+(k-1)*3*n的
地址,并且必须在每次随机访问数组时计算它。地址的计算包括3次整数乘法(每次3个CPU周期)和至少3次加法(每次1个周期)。但是,编译器可以使用相对地址优化常规访问(可预测)

如果您有不同的1索引数组,则地址的计算只涉及一个整数加法(1个周期),因此,在使用单个3索引数组时,每次访问的性能损失至少为11个周期

此外,如果您有9个不同的数组,那么它们中的每一个都可以在缓存线边界上对齐,而您将被迫在行尾使用填充来确保单个数组的这种行为

因此我想说的是,在
A(n,3,3)
的特殊情况下,由于最后两个索引很小,并且在编译时已知,因此可以安全地将其转换为9个不同的数组,以潜在地获得一些性能

请注意,如果您经常以随机顺序使用同一索引
i
中9个数组的数据,则将数据重新组织为
a(3,3,n)
将显著提高性能。如果a是双精度的,
a(4,4,n)
如果
a
在64字节边界上对齐,则可能会更好