Java: многомерный массив по сравнению с одномерным

Например:

  • a) int [x][y][z]

    по сравнению с

  • b) int[x*y*z]

Первоначально мысль я пошел бы с a) для простоты.

Я знаю, что Java не хранит массивы линейно в памяти как C, делает, но какие последствия это имеет для моей программы?

27
задан 0xCursor 27 October 2019 в 01:49
поделиться

0 ответов

Обычно лучше всего искать ответы на такие вопросы, чтобы увидеть, как варианты компилируются в байт-код JVM:

multi = new int[50][50];
single = new int[2500];

Это переводится на:

BIPUSH 50
BIPUSH 50
MULTIANEWARRAY int[][] 2
ASTORE 1
SIPUSH 2500
NEWARRAY T_INT
ASTORE 2

Итак, как вы можете видеть, JVM уже знает, что мы говорим о многомерном массиве.

Продолжая:

for (int i = 0; i < 50; ++i)
    for (int j = 0; j < 50; ++j)
    {
        multi[i][j] = 20;
        single[i*50+j] = 20;
    }

Это переводится (пропуская циклы) в:

ALOAD 1: multi
ILOAD 3: i
AALOAD
ILOAD 4: j
BIPUSH 20
IASTORE

ALOAD 2: single
ILOAD 3: i
BIPUSH 50
IMUL
ILOAD 4: j
IADD
BIPUSH 20
IASTORE

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

Я не думаю, что производительность будет такой проблемой.

РЕДАКТИРОВАТЬ:

Я сделал несколько простых тестов, чтобы увидеть, что здесь происходит. Я решил попробовать разные примеры: линейное чтение, линейная запись и произвольный доступ. Время выражается в миллисекундах (и рассчитывается с использованием System.nanoTime(). Вот результаты:

Линейная запись

  • Размер: 100x100 (10000) Мульти: 5.786591 Одиночный: 6.131748
  • Размер: 200x200 (40000) Мульти: 1.216366 Одноместный: 0,782041
  • Размер: 500x500 (250000) Мульти: 7.177029 Одноместный: 3.667017
  • Размер: 1000x1000 (1000000) Мульти: 30.508131 Одноместный: 18.064592
  • Размер: 2000x2000 (4000000) Мульти: 185.3548 Одноместный: 155.590313
  • Размер: 5000x5000 (25000000) Мульти: 955.5299 Одноместный: 923.264417
  • Размер: 10000x10000 (100000000) Мульти : 4084.798753 Одиночный: 4015.448829

Линейное чтение

  • Размер: 100x100 (10000) Мульти: 5.241338 Одноместный: 5.135957
  • Размер: 200x200 (40000) Мульти : 0.080209 Одноместный: 0.044371
  • Размер: 500x500 (250000) Мульти: 0.088742 Одноместный: 0.084476
  • Размер: 1000x1000 (1000000) Мульти: 0.232095 Одноместный: 0.167671
  • Размер: 2000x2000 (4000000) Мульти: 0,481683 Одноместный: 0,33321
  • [1 118] Размер: 5000x5000 (25000000) Мульти: 1.222339 Один: 0.828118 Размер: 10000x10000 (100000000) Мульти: 2.496302 Один: 1.650691

Случайное чтение

  • Размер: 100x100 ( 10000) Multi: 22,317393 Single: 8.546134
  • Размер: 200x200 (40000) Multi: 32.287669 Single: 11.022383
  • Размер: 500x500 (250000) Multi: 189.542751 Single: 68.181343
  • Размер: 1000x1000 (1000000) Мульти: 1124.78609 Одноместный: 272.235584
  • Размер: 2000x2000 (4000000) Мульти: 6814.477101 Одноместный: 1091.998395
  • Размер: 5000x5000 (25000000) Мульти: 50051.306239 Один: 7028.422262 ]

Случайное число немного вводит в заблуждение, поскольку оно генерирует 2 случайных числа для многомерного массива, в то время как только одно для одномерного (и PNRG могут потреблять некоторое количество ресурсов ЦП).

Имейте в виду, что я пытался чтобы позволить JIT работать, измеряя только после 20-го запуска того же цикла. Для полноты картины моя виртуальная машина Java выглядит следующим образом:

Java-версия «1.6.0_17» Java (TM) SE Runtime Environment (сборка 1.6.0_17-b04) Java HotSpot (TM) 64-разрядная виртуальная машина сервера (сборка 14.3-b01, смешанный режим)

68
ответ дан Alexander Stepchkov 28 November 2019 в 04:10
поделиться

Используйте первый вариант (3-мерный), потому что его легче понять и меньше шансов сделать какую-то логическую ошибку (особенно если вы используете его для моделирования 3-мерного пространства)

4
ответ дан Roman 28 November 2019 в 04:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: