Подтвердить что ты не робот

Производительность 2-мерного массива по сравнению с одномерным массивом

В C есть разница во времени и пространстве между m × n двумерным массивом vs одномерного массива длины m × n (при больших значениях m и n)? Будет ли доступ к элементам быстрее с 1-мерным массивом?

4b9b3361

Ответ 1

В C двумерные массивы - это просто аккуратная схема индексирования для одномерных массивов. Так же, как с 1D-массивом, 2D-массивы выделяют один блок смежной памяти, а обозначение A[row][col] похоже на выражение A[row*NCOLS+col].

Обычно, если вы должны были реализовать свои собственные многомерные массивы с использованием одномерных массивов, вы должны написать функцию индексирования:

int getIndex(int row, int col) { return row*NCOLS+col; }

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

Чтобы проиллюстрировать:

#define NROWS 10
#define NCOLS 20

Это:

int main(int argc, char *argv[]) {
    int myArr[NROWS*NCOLS];
    for (int i=0; i<NROWS; ++i) {
       for (int j=0; j<NCOLS; ++j) {
          myArr[getIndex(i,j)] = i+j;
       }
    }
    return 0;
}

Должно выполняться так же, как это:

int main(int argc, char *argv[]) {
    int myArr[NROWS][NCOLS];
    for (int i=0; i<NROWS; ++i) {
       for (int j=0; j<NCOLS; ++j) {
          myArr[i][j] = i+j;
       }
    }
    return 0;
}

Хотя AraK указал, если вы много прыгаете вокруг строк, а строки очень велики, вы можете поразить множество ошибок страницы... в этом случае может помочь пользовательская функция индексирования (с переключением строк и столбцов), но может просто изменить какой размер в двумерном массиве вы обрабатывать как строки и которые вы рассматриваете как столбцы.

Ответ 2

Собственно, если вы используете так называемый двумерный массив в C, компилятор выполнит преобразование в одномерный массив для вас. Если вы используете одномерный массив, и вам нравится относиться к нему как к двумерному, вы должны сами написать отображение.

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

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

Ответ 3

Я не думаю, что есть какая-то разница. Внутри c обрабатывает двумерный массив, например, несколько одномерных массивов.

Однако, как и при любой производительности, ваш пробег может отличаться. Может быть какая-то тонкая арифметическая разница указателя. Запускайте тесты по времени в обоих сценариях. Какой бы ни побежал быстрее.

Ответ 4

Роберт прав. Выражения индексирования скомпилированы для арифметических выражений указателя, и поэтому нет никакой разницы.

Что может повлиять на порядок доступа, и поэтому вы можете сами реализовать вещи, чтобы вы могли контролировать порядок доступа. Например, первая строка первой и первой строки строки.

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

Ответ 5

Как говорится другим, разница в том, как вы получаете доступ к своим элементам: что имеет значение, если ваши элементы являются макетом в памяти, который является линейным, по крайней мере, на общих архитектурах. Итак, все, что у вас на самом деле - это 1d-массив, 2d и т.д. - это просто "удобство", а разумный компилятор должен оптимизировать индексирование, но на практике, когда у вас есть несколько переменных, компиляторы часто терпят неудачу на arch например x86 из-за голодания регистра.

Теперь это зависит от вашего приложения, но я думаю, что вы должны думать с 1d макетом по умолчанию, особенно если вам нужно обрабатывать несколько измерений. Первая проблема с многомерными массивами в C состоит в том, что вы не можете их динамически распределять - если вы распределяете по каждой строке, у вас будут ужасные характеристики, потому что у вас нет смежной части памяти. Подробнее об этом см. FFTW doc.

Обратите внимание, что вы всегда можете описать свою единую память с удобной индексацией массива поверх нее (вы выделяете один большой блок памяти nxm, а затем создаете массив из n указателя на каждую строку).

Ответ 6

Я только догадываюсь, но я бы сказал, что 1d-массив быстрее, чем 2d-массив. Однако это было бы не намного быстрее. Вид как $1,000,000.01 составляет более $1,000,000.

Я бы использовал все, с чем проще кодировать.