Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.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++ 高效访问存储为一维阵列的三维阵列_C++_C_Arrays_Multidimensional Array_Fft - Fatal编程技术网

C++ 高效访问存储为一维阵列的三维阵列

C++ 高效访问存储为一维阵列的三维阵列,c++,c,arrays,multidimensional-array,fft,C++,C,Arrays,Multidimensional Array,Fft,我有一个3D数组,它以列方式存储为一维数组。比如说, for( int k = 0; k < nk; k++ ) // Loop through the height. for( int j = 0; j < nj; j++ ) // Loop through the rows. for( int i = 0; i < ni; i++ ) // Loop through the columns. { ijk = i

我有一个3D数组,它以列方式存储为一维数组。比如说,

for( int k = 0; k < nk; k++ ) // Loop through the height.
    for( int j = 0; j < nj; j++ ) // Loop through the rows.
        for( int i = 0; i < ni; i++ ) // Loop through the columns.
        {
            ijk = i + ni * j + ni * nj * k;
            my3Darray[ ijk ] = 1.0;
        }

我的计算效率高吗?是否有可能将
my3Darray
直接传递给处理向量FFT的函数(而不是将向量复制到
myvec
)?

当所有内容都缩减到最里面的位和字节时,三维数组当然会存储在一维内存中。因此,给定数组元素的三个维度,编译器生成的代码与您自己计算数组元素位置的代码几乎相同。惊喜

换句话说,这几乎是一样的

对于显式三维数组,唯一对编译器有利的事情是编译器知道所有内部维度的大小,如果最内部维度切片的大小恰好是方便的,比如2的幂,编译器可能会用等效的左移位替换一些乘法,我想这会稍微快一点,然后是一个完整的乘法指令。但如果结果是性能上的巨大差异,我会感到惊讶


选择维度的相对顺序可能更为重要,这样,用于转换的典型访问模式将对CPU缓存更为友好。

您可以通过预先计算这样的步长来减少倍数:

...
for( int j = 0; j < nj; j++ ) // Loop through the rows.
{
    int stride = ni * nj;
    ijk = i + ni * j;
    for( int k = 0; k < nk; k++ ) // Loop through the heights.
    {
        myvec[ k ] = my3Darray[ ijk ];
        fft( myvec, myvec_processed );
        ijk += stride;
    }
}
。。。
for(int j=0;j

但这只会让事情加快一点。由于以非顺序方式访问
my3Darray
,您仍然会遇到缓存问题。

您不能将k设置为最内部的变量,这样您就不会跳入
ni*nj
步骤,而是按1,使其对缓存友好。你能做的不多了。我需要计算所有向量的FFT:行方向、列方向以及高度方向。你说的是高度。。。是什么让你觉得它现在很慢,更重要的是,它可以改进。您展示了最不利于缓存的示例(顺便说一句,高度也是如此)。同样,在我看来,除了为所显示的代码改进缓存友好性之外,没有什么可以做的了。希望我错了。我实际上会尝试的一件事是,复制整个数组,对其重新编制索引。可能两次跳跃为1的迭代比一次跳跃较大的迭代要快,但这取决于CPU缓存预测器的智能程度。您可以用
ijk+=stride替换复杂的乘法行如果计算
跨步
并在循环外初始化
ijk
。但是不幸的是,如果您不按顺序访问,您仍然会遇到缓存问题。
...
for( int j = 0; j < nj; j++ ) // Loop through the rows.
{
    int stride = ni * nj;
    ijk = i + ni * j;
    for( int k = 0; k < nk; k++ ) // Loop through the heights.
    {
        myvec[ k ] = my3Darray[ ijk ];
        fft( myvec, myvec_processed );
        ijk += stride;
    }
}