Сравнение производительности массива массивов и многомерных массивов

Когда я использовал C ++ в колледже, мне посоветовали использовать многомерные массивы (далее MDA), когда это возможно, поскольку он демонстрирует лучшую локальность памяти, так как он выделяется одним большим блоком. С другой стороны, массив массивов (AoA) распределяется по нескольким более мелким кускам, возможно, разбросанным по всей физической памяти, где бы ни находились вакансии.

Итак, я предполагаю, что первый вопрос: это миф или этому совету стоит следовать?

Если предположить, что это последнее, то следующий вопрос будет заключаться в том, что делать на таком языке, как Java, у которого нет настоящего MDA. Конечно, не так уж и сложно подражать MDA с помощью 1DA. По сути, то, что является синтаксическим сахаром для языков с MDA, может быть реализовано как поддержка библиотек для языков без MDA.

Стоит ли это усилий? Это слишком низкий уровень проблемы оптимизации для такого языка, как Java? Должны ли мы просто отказаться от массивов и использовать List даже для примитивов?


Другой вопрос: в Java, может ли выделение AoA сразу (new int[M][N]) привести к другому распределению памяти, чем при иерархическом (new int[M][]; for (... new int[N])?


person polygenelubricants    schedule 03.03.2010    source источник
comment
См. Также stackoverflow.com/questions / 2512082 /, в котором приведены фактические результаты тестов.   -  person rwong    schedule 16.03.2013


Ответы (4)


Java и C # выделяют память совершенно иначе, чем C ++. Фактически, в .NET наверняка все массивы AoA будут близко друг к другу, если они будут выделены один за другим, потому что в памяти есть только один непрерывный фрагмент без какой-либо фрагментации.

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

person vava    schedule 03.03.2010
comment
Например, экземпляр int [128] [2] занимает 3600 байт. По сравнению с 1040 байтами, которые использует экземпляр int [256] (который имеет такую ​​же емкость), 3600 байтов представляют собой 246-процентные накладные расходы. - javaworld.com/article/2077496/testing-debugging/ - person Ghandhikus; 08.11.2016

Стоит ли это усилий? Это слишком низкий уровень проблемы оптимизации для такого языка, как Java?

Вообще говоря, это не стоит усилий. Лучшая стратегия, чтобы забыть об этой проблеме в первой версии вашего приложения и реализовать ее простым (то есть простым в обслуживании) способом. Если первая версия работает слишком медленно для ваших требований, воспользуйтесь инструментом профилирования, чтобы найти узкие места приложения. Если профилирование предполагает, что массивы массивов, вероятно, являются проблемой, проведите несколько экспериментов, чтобы изменить структуры данных на моделируемые многомерные массивы и профилировать, чтобы увидеть, имеет ли это существенное значение. [Я подозреваю, что это не будет иметь большого значения. Но самое важное - не тратить время на оптимизацию чего-то без надобности.]

Должны ли мы просто отказаться от массивов и использовать списки даже для примитивов?

Я бы не пошел так далеко. Предполагая, что вы имеете дело с массивами заранее определенного размера:

  • массивы объектов будут немного быстрее, чем эквивалентные списки объектов, и
  • массивы примитивов будут значительно быстрее и занимать значительно меньше места, чем эквивалентные списки примитивов-оберток.

С другой стороны, если вашему приложению необходимо «увеличить» массивы, использование списка упростит ваш код.

person Stephen C    schedule 03.03.2010

Я бы не стал тратить силы на использование одномерного массива в качестве многомерного массива в Java, потому что здесь нет синтаксиса, который мог бы помочь. Конечно, можно определить функции (методы), чтобы скрыть работу за вас, но при использовании массива массивов вы просто вызываете функцию, а не следуете за указателем. Даже если компилятор / интерпретатор ускорит это для вас, я все равно не думаю, что это того стоит. Кроме того, вы можете столкнуться с проблемами при попытке использовать код, который ожидает массивы 2D (или N-Dim), которые ожидаются как массивы массивов. Я уверен, что наиболее общий код будет написан для таких массивов на Java. Также можно дешево переназначить строки (или столбцы, если вы решите так думать).

Если вы знаете, что этот массив multidim является узким местом, вы можете проигнорировать то, что я сказал, и посмотреть, поможет ли ручная оптимизация.

person Thomas Eding    schedule 03.03.2010

Из личного опыта в Java, многомерные массивы намного медленнее, чем одномерные массивы, если загружается большой объем данных или осуществляется доступ к элементам данных, которые находятся в разных положениях. Я написал программу, которая делала снимок экрана в формате BMP, а затем просматривала снимок экрана в поисках меньшего изображения. Загрузка снимка экрана (примерно 3 мб) в многомерный массив (трехмерный, [xPos] [yPos] [color] (где color = 0 - значение красного цвета и так далее)) заняла 14 секунд. Чтобы загрузить его в одномерный массив, потребовалась 1 секунда. Выигрыш от нахождения меньшего изображения на большом изображении был аналогичным. На поиск меньшего изображения в большом изображении ушло около 28 секунд, когда оба изображения хранились в виде многомерных массивов. Поиск меньшего изображения в большом изображении занимал около секунды, когда оба изображения хранились в виде одномерных массивов. Тем не менее, я сначала написал свою программу, используя размерные массивы для удобства чтения.

person William Royle    schedule 29.08.2013
comment
Вы уверены, что проблема в массиве? Легко сказать, что в Java что-то работает медленно, не понимая, как работает JVM ... Вы должны учитывать время прогрева и тип JVM, который вы используете (клиент или сервер). На ранних стадиях, когда программа только запускается, вы обнаружите более медленные скорости. - person ceklock; 30.08.2013