Эффективный доступ к 3D-массиву, хранящемуся как 1D-массив

0

У меня есть трехмерный массив, который хранится в виде массива 1D по порядку. Например,

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. По высоте я имею в виду векторы в третьем измерении массива. Мне нужно это, потому что я хочу обработать БПФ каждого вектора и вернуть полученный вектор. Я был бы благодарен за то, что мои друзья подумали о stackoverflow, как я могу эффективно обращаться к этим векторам. Конечно, одна тривиальная возможность, например, для векторов высоты:

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

        // Store the results in a new array, which is storing myvec_processed in my3Darray_fft_values.
        for( int k = 0; k < nk; k++ ) // Loop through the heights.
        {
            ijk = i + ni * j + ni * nj * k;
            my3Darray_fft_values[ ijk ] = myvec_processed[ k ];
        }
    }

Я эффективно это вычисляю? Есть ли возможность передать my3Darray непосредственно функции, которая обрабатывает БПФ векторов (вместо копирования вектора на myvec)?

  • 1
    Разве вы не можете сделать k самой внутренней переменной, чтобы не переходить ni * nj шаг ni * nj а на 1, чтобы сделать ее более удобной для кэширования. Больше ничего не поделаешь.
  • 0
    Мне нужно рассчитать БПФ для всех векторов: по строкам, по столбцам, а также по высоте.
Показать ещё 2 комментария
Теги:
arrays
multidimensional-array
fft

2 ответа

1

Вы можете сократить умножения, предварительно вычислив такой шаг:

...
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;
    }
}

Но это лишь немного ускорит процесс. У вас все еще будут проблемы с кешем из-за доступа к my3Darray в несущественном виде.

0

Когда все сводится к его внутренним битам и байтам, ваш трехмерный массив, конечно, сохраняется в одномерной памяти. Таким образом, при заданном элементе массива три измерения, компилятор производит почти такой же код для вычисления местоположения элемента массива, как вы делаете сами. Сюрприз!

Так, другими словами, это почти то же самое.

Единственное, что может работать в компиляторе, с явными 3-мерными массивами, состоит в том, что компилятор знает размеры всех внутренних измерений, и если размер самого внутреннего мерного среза оказывается чем-то удобным, как сила 2, компилятор мог бы заменить некоторые из умножений эквивалентными сдвигами влево, что было бы немного быстрее, я полагаю, а затем полномасштабную инструкцию умножения. Но я был бы удивлен, если бы это оказалось большой разницей в производительности.

Вероятнее всего, важно выбрать относительный порядок ваших измерений, так что ваши типичные шаблоны доступа для ваших преобразований будут более дружественными к кэшу кэш-памяти.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню