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

Странное поведение оптимизатора условий цикла Hotspot

Основываясь на обсуждениях вокруг ответа на этот вопрос, я обнаружил действительно странное поведение оптимизатора Java Hotspot. Наблюдаемое поведение, по крайней мере, можно увидеть в Oracle VM 1.7.0_17, но, похоже, оно встречается и в более старых версиях Java 6.

Прежде всего, я уже знал, что оптимизатор, очевидно, осознает, что некоторые методы в стандартном API являются инвариантными и не имеют побочных эффектов. При выполнении цикла, такого как double x=0.5; for(double d = 0; d < Math.sin(x); d += 0.001);, выражение Math.sin(x) не оценивается для каждой итерации, но оптимизатор знает, что метод Math.sin не имеет соответствующих побочных эффектов и что результат является инвариантным, пока x не изменяется в цикле.

Теперь я заметил, что простое изменение x от 0.5 до 1.0 отключает эту оптимизацию. Дальнейшие тесты показывают, что оптимизация разрешена только в том случае, если abs (x) ASIN (1/SQRT (2)). Есть ли веская причина для этого, чего я не вижу, или это лишнее ограничение оптимизационных условий?

Изменить: оптимизация, похоже, реализована в hotspot/src/share/vm/opto/subnode.cpp

4b9b3361

Ответ 1

Я думаю, что ваш вопрос о конкретном JVM Oracle, поскольку реализация Math зависит от реализации. Вот хороший ответ о реализации Dalvik, например: родной код для Java Math class

Обычно

  • sin (a) * sin (a) + cos (a) * cos (a) = 1
  • sin (pi/2 - a) = cos (a)
  • sin (-a) = -sin (a)
  • cos (-a) = cos (a)

поэтому нам не нужна реализация функций sin/cos для x < 0 или x > pi/4.

Я полагаю, что это ответ (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5005861):

Мы знаем результаты almabench и статью osnews о тригонометрическая производительность. Тем не менее, реализация HotSpot sin/cos на x86 в течение многих лет использовал и продолжает использовать fsin/fcos x87 инструкции в диапазоне, в котором эти инструкции соответствуют качеству требования к реализации, в основном [-pi/4, pi/4]. Вне этого диапазон результатов fsin/fcos может находиться где угодно в диапазоне [-1, 1] с небольшим отношением к истинному синусу/косинусу аргумента. Для Например, fsin (Math.PI) получает только половину цифр результата верный. Причина этого в том, что команда fsin/fcos в реализациях используется менее идеальный алгоритм для аргумента сокращение; процесс сокращения аргументов объясняется ошибкой 4857011.

Заключение: вы видели результаты алгоритма сокращения аргументов в действии, а не ограничение оптимизации.