Почему Java SIMD (Панама) медленнее, чем скалярная?

Я следил за инструктором Intel для SIMD на Java с Панама. Я хочу проделать несколько простых операций с массивами:

Вот скалярный и векторный цикл с сайта:

public static void scalarComputation(float[] a, float[] b, float[] c) {
    for (int i = 0; i < a.length; i++) {
        c[i] = (a[i] * a[i] + b[i] * b[i]) * - 1.0f;
    }
}

public static void vectorComputation(float[] a, float[] b, float[] c) {
    int i = 0;
    for (; i < (a.length & ~(species.length() - 1));
         i += species.length()) {
        FloatVector<Shapes.S256Bit> va = speciesFloat.fromArray(a, i);
        FloatVector<Shapes.S256Bit> vb = speciesFloat.fromArray(b, i);
        FloatVector<Shapes.S256Bit> vc = va.mul(va).
                add(vb.mul(vb)).
                neg();
        vc.intoArray(c, i);
    }

    for (; i < a.length; i++) {
        c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f;
    }
}

Когда я измеряю время:

float [] A = new float[N];
float [] B = new float[N];
float [] C = new float[N];

for(int i = 0; i < C.length; i++)
{
    C[i] = 2.0f;
    A[i] = 2.0f;
    B[i] = 2.0f;
}

long start = System.nanoTime();
for(int i = 0; i < 200; i++)
{
    //scalarComputation(C,A,B);
    //vectorComputation(C,A,B);
}
long end = System.nanoTime();        
System.out.println(end - start);

У меня всегда больше времени для вектора, чем для скаляра. Вы знаете почему? Спасибо.

Какое значение имеет N в ваших тестах?

Ramón J Romero y Vigil 07.06.2018 13:54

Для небольших (достаточно) векторов накладные расходы на передачу информации механизму векторной обработки превысят экономию,

Stephen C 07.06.2018 13:59

N равно 345600 = 480 * 720

K.Vu 07.06.2018 13:59

@StephenC: Я предполагаю, что OP находится на x86-64, где все текущие микроархитектуры тесно интегрируют векторные ALU очень. Стоит использовать SIMD для копирования 16 байт, если источник еще не был в целочисленных регистрах! Скалярная математика FP в любом случае использует те же регистры XMM0..15, что и векторная математика, например addss (скалярная одинарная точность) вместо addps (в упаковке одинарной точности). Для 256-битных векторов потребуются регистры YMM (если Панама не эмулирует широкие векторы поверх 128-битных SIMD ...). XMM0..15 - нижние половинки YMM0..15

Peter Cordes 07.06.2018 14:15

Если вы повторяете это только 200 раз, вы можете увидеть 256-битные эффекты запуска AVX. Если это работает с ~ 8 числами с плавающей запятой за такт (1 vmulps + 1 vfmsubps), ваш интервал тестирования может быть всего 2 мс на Haswell или Skylake с тактовой частотой 4 ГГц. Это все еще 8 миллионов тактовых циклов, так что вы, вероятно, в порядке с включением верхних половин исполнительных блоков. Агнер Фог заметил, что период разминки на Skylake составляет 14 часов: agner.org/optimize/blog/read.php?i=415#415. (И, кстати, 8 чисел с плавающей запятой mul + FMA за такт на самом деле здесь невозможно из-за узкого места во внешнем интерфейсе из инструкций load + store.)

Peter Cordes 07.06.2018 14:23

@ K.Vu: вы разогрели JVM, чтобы было время для JIT-компиляции горячего цикла? И вы проверяли, что скалярная версия не оптимизирует работу в цикле? (Ничего не читает результат). Хорошая проверка состоит в том, что время линейно зависит от количества повторов. Если он масштабируется, но не линейно, накладные расходы на запуск являются проблемой. Если он не масштабируется, ваш тест будет оптимизирован. Если он линейный, то, возможно, вы измеряете то, что планировали (но все же нет гарантии).

Peter Cordes 07.06.2018 14:32

На каком оборудовании вы тестируете? Если вы включите JIT-скомпилированный asm для внутреннего цикла в свой вопрос (Как увидеть JIT-скомпилированный код в JVM?) и отметите [x86], я могу сказать вам, почему версия в Панаме медленнее (если это не была ошибка измерения), если вы используете x86 (agner.org/optimize). например возможно, JIT-компилятор автоматически векторизует ваш простой скалярный цикл, используя лучший выбор инструкций, если ваш панамский код заставляет фактическое умножение на -1.0 вместо SUB или FMSUB вместо ADD или FMADD. Или неправильно выровненные массивы на Sandybridge?

Peter Cordes 07.06.2018 14:51

У меня процессор Intel (R) Core (TM) i7-7500U @ 2,70 ГГц. Кэш L1 составляет 128 КБ, L2 - 512 КБ, а L3 - 4096 КБ. Я только что установил -XX: TypeProfileLevel = 121 -XX: + UseVectorApiIntrinsics в моей конфигурации запуска.

K.Vu 07.06.2018 15:00

Я уже сделал проект HPC на C с SSE и SSE2, и мне было любопытно, может ли Java сделать то же самое.

K.Vu 07.06.2018 15:04

Вам действительно нужно написать правильный тест. Java требуется некоторое время (секунды), прежде чем она будет работать должным образом быстро, а результаты теста покажутся всего лишь миллисекундами. Забудьте об этом, используйте JMH, все остальное тратит время.

maaartinus 07.06.2018 15:19
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
5
10
1 575
1

Ответы 1

Вы используете неправильную ветку: создайте из вектор. Вам также необходимо использовать JMH для получения правильных измерений - здесь - это некоторые сторонние тесты, написанные для Vector API.

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

Как вы пришли к выводу, что OP использует неправильную ветку - я не вижу этого, упомянутого в их сообщении?

Ben Hutchison 16.02.2021 11:35

Другие вопросы по теме