Java автовекторизация - PullRequest
       37

Java автовекторизация

0 голосов
/ 03 сентября 2018

Я пытаюсь понять, когда JDK будет автоматически векторизоваться. У меня есть следующий набор вопросов (несмотря на поиск в Google, чтение, эксперименты и т. Д.). Дан простой цикл следующим образом:

for(int i=0; size = size(); i < size; i++) {
   a[i] = b[i] * c[i];
   method1();
   // someObject.method2();
   // someHashMap.put(b[i], c[i]);
}
  1. Почему необходимо, чтобы вызов метода "method1" (который появляется внутри цикла) был встроен для автоматической векторизации в ocurr? (Я не могу понять, почему это должно быть необходимым ....)
  2. Возможно, это «глупый» вопрос, но что, если «someObject.method2 ()» не было прокомментировано. (И давайте предположим, что method2 - это огромный метод, т.е. много строк). Это также предотвратит автовекторизацию? Что, если method2 был крошечным методом (например, всего одна или две строки и т. Д.?)
  3. Что если строка "someHashMap" не закомментирована? Приведет ли тот факт, что у нас есть объект / переменная, которая будет распределена по всем SIMD, также приведет к сбою автовекторизации? (Я не могу понять, как это может работать, если jdk каким-то образом автоматически не вставит ключевое слово syncronization при доступе к общему объекту / var для someHashMap
  4. Мне кажется, что «потоковый» интерфейс решил бы проблему, подразумеваемую в вопросе № 3 непосредственно выше, поскольку логика «сборщика» в потоках автоматически позаботилась бы о слиянии отдельных хэш-карт, и поэтому нам не нужно было бы синхронизировать " слово. (И вообще, почти кажется, что потоковый API - это идеальный API, позволяющий jdk автоматически использовать автовекторизацию, если при создании потокового кода нет «внешних переменных» (то есть никаких побочных эффектов) ... Есть ли jdk Компилятор / jit автоматически выполняет автовекторизацию в результате, когда код пишется с использованием стандартного потокового интерфейса? Если нет, то не имеет ли это смысла (возможно, в будущей версии jdk или, возможно, jdk от какого-либо другого поставщика?)
  5. Если тело цикла содержит много операторов if и т. Д. (Много ветвлений и, скажем, далее, что каждая ветвь выполняет много вычислений), это будет означать, что а) автовекторизация, вероятно, является ПЛОХОЙ идеей (как это было бы) для графического процессора) и б) Jit-компилятор достаточно умен, чтобы определить, что автовекторизация - плохая идея, и поэтому он не будет автовекторизоваться?
  6. В настоящее время я использую Oracle jdk8, но меняются ли ответы выше, если кто-то использует jdk9 или jdk10 и т. Д .?

1 Ответ

0 голосов
/ 04 сентября 2018

Чтобы ответить на ваш вопрос (1), в принципе, компилятор Java может оптимизировать при наличии не встроенного вызова method1(), , если , он проанализировал method1() и определил, что он не ' У него нет побочных эффектов, которые могут повлиять на автоматическую векторизацию. В частности, компилятор может доказать, что метод был «постоянным» (без побочных эффектов и без чтения из глобальной памяти), что в целом позволило бы выполнить много оптимизаций на сайте вызова без встраивания. Возможно, это также может доказать более ограниченные свойства, такие как не чтение или запись в массивы определенного типа, что также будет достаточно для того, чтобы в этом случае происходила автоматическая векторизация.

На практике , однако, я не знаю ни одного компилятора Java, который может сделать эту оптимизацию сегодня. Если этот ответ , как полагают, в Hotspot: "вызов [not-inlined] метода обычно непрозрачен для JIT-компилятора." Большинство Java-компиляторов так или иначе основаны на Hotspot, так что я не ожидаю, что есть сложный Java-компилятор, который может это сделать, если Hotspot не может.

Этот ответ также охватывает некоторые причины, по которым такой межпроцедурный анализ (ПНД) может быть как сложным, так и не особенно полезным. В частности, методы, о которых можно доказать нетривиальные вещи, часто бывают достаточно малы, чтобы их в любом случае указывали. Я не уверен, полностью ли я согласен: можно также утверждать, что Java агрессивно частично использует , потому что не выполняет IPA, поэтому сильный IPA, возможно, откроет возможность делать меньше встроенных и, следовательно, уменьшит время выполнения. код и время JIT.

Другие варианты методов, о которых вы спрашиваете в (2) или (3), ничего не меняют: компилятору по-прежнему нужно, чтобы IPA разрешил его векторизацию, и, насколько я знаю, в компиляторах Java его нет.

(4) и (5) кажется, что их следует задавать как совершенно отдельные вопросы.

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

Наконец, стоит отметить, что даже в отсутствие IPA и ничего не зная о method1(), компилятор мог бы оптимизировать математические вычисления на a, b и c, если бы мог доказать, что ни один из них не сбежал , Хотя это кажется довольно бесполезным в общем: это означало бы, что все эти переменные были бы распределены в этой функции (или какой-либо функции, встроенной в эту), тогда как я бы предположил, что в большинстве реалистичных сценариев по крайней мере одна из трех передается в вызывающим абонентом.

...