Целочисленное сложение производительности в Java - PullRequest
3 голосов
/ 31 января 2012

Я тестирую производительность при сложении целых чисел в Java. То, как я это сделал, суммировал миллиарды целых чисел. Пример файла, который я использую для тестирования, представляет собой двоичный файл 1G. Моя программа так же проста, как показано во фрагменте ниже.

int result = 0;
FileChannel fileChannel = new FileInputStream(filename).getChannel();
long fileSize = fileChannel.size();
intBuffer = fileChannel.map(MapMode.READ_ONLY, startPosition, fileSize).asIntBuffer();

try {
  while (true) {
    result += intBuffer.get();
  }
} catch (BufferUnderflowException e) {
  System.out.println("Complete reading");
}

Как видно из приведенного выше, он просто выполняет две операции в каждом цикле

  • чтение целого числа из файла
  • целочисленное сложение

Эта программа работала около 2 минут на моей машине. Я также выполнил еще один тестовый прогон без добавления, изменив result += intBuffer.get() на result = intBuffer.get() (как показано в следующем фрагменте).

int result = 0;
FileChannel fileChannel = new FileInputStream(filename).getChannel();
long fileSize = fileChannel.size();
intBuffer = fileChannel.map(MapMode.READ_ONLY, startPosition, fileSize).asIntBuffer();

try {
  while (true) {
    result = intBuffer.get();
  }
} catch (BufferUnderflowException e) {
  System.out.println("Complete reading");
}

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

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

int result = random.nextInt();
int other = random.nextInt();
int num = 1073741824 / 4;
while(num-- > 0) {
  result += other;
}

При таком же количестве целочисленных сложений и целочисленных инкрементных операций эта программа завершается менее чем за 1 секунду.

Мой вопрос

  • Чем вызвана основная разница во времени между этими прогонами? Компилятор Java делает что-то для оптимизации последнего?

Любые мысли приветствуются.

Ответы [ 3 ]

4 голосов
/ 31 января 2012

Это потому, что дисковый ввод / вывод очень медленный по сравнению с процессором.

В первом случае вы читаете из файла.Таким образом, вы ограничены доступом к диску.

Во втором случае все это в процессоре.


Так что это не имеет никакого отношения к скорости добавления.

  • Первый случай ограничен скоростью вашего диска.
  • Второй случай (вероятно) ограничен скоростью генератора случайных чисел.

Что касается того, почему result = intBuffer.get() кажется очень быстрым: (взято из комментариев)

Я могу придумать две возможные причины:

  • Устранение мертвого кода с помощью JIT оптимизирует все, кроме последней итерации.
  • Буферизация ввода / вывода: Операционная система буферизует весь файл в память после первойчитать. *

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

1 голос
/ 31 января 2012

Большая разница в том, что вы делаете файл IO.Суммирование целых чисел не проблема.Но это читает их.Я не очень уверен, но я думаю, что чтение одного ГБ данных за две минуты приемлемо.

0 голосов
/ 31 января 2012

Это потому, что доступ к вводу / выводу - это ваша горлышко от бутылки.Посчитайте время только на этапе сложения.Вы всегда можете загрузить все данные в ОЗУ (например, массив int) и начать отсчет времени с этого момента.

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

...