Что может привести к тому, что продукт DOT AVX2 будет работать по -разному для разных пробежек?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Что может привести к тому, что продукт DOT AVX2 будет работать по -разному для разных пробежек?

Сообщение Anonymous »

Я пишу точечный калькулятор продукта для AVX2. Я пытаюсь сравнить это, но та же программа работает по -разному среди пробежек. Я пытаюсь найти причину. Сначала я подозревал, что выравнивание данных может вызвать проблему, но даже после выравнивания данных по границе 4K, проблема сохраняется. Данные настолько малы, что должны вписаться в кэш L1. Моя тестовая программа работает за 2,3-3,0 секунды. Но даже если я увеличу количество итерации до 10 раз, время выполнения варьируется от 23-28 сек. Я ожидаю, что гораздо меньше вариаций. Linux Kernel 6.11 и губернатор ЦП устанавливаются на производительность. Я не думаю, что проблема-дросселя процессора, кажется, что во время программы пробег процессор работает на ~ постоянной 4,7-4,8 ГГц. Я делал тесты на этом компьютере раньше, результаты имели гораздо меньшую дисперсию для другого кода. Количество инструкций одинаково, но количество циклов варьируется. Быстро, запустить через 2,3 сек: < /p>

Код: Выделить всё

 Performance counter stats for './t':

2328.22 msec task-clock                       #    1.000 CPUs utilized
32      context-switches                 #   13.744 /sec
6      cpu-migrations                   #    2.577 /sec
65      page-faults                      #   27.918 /sec
10783895775      cpu_core/cycles/                 #    4.632 GHz
33906242851      cpu_core/instructions/           #   14.563 G/sec
1701192939      cpu_core/branches/               #  730.685 M/sec
18621      cpu_core/branch-misses/          #    7.998 K/sec

2.329005509 seconds time elapsed

2.328711000 seconds user
0.000000000 seconds sys
< /code>
Медленно, запустите через 2,9 сек: < /p>
 Performance counter stats for './t':

2855.76 msec task-clock                       #    1.000 CPUs utilized
26      context-switches                 #    9.104 /sec
0      cpu-migrations                   #    0.000 /sec
66      page-faults                      #   23.111 /sec
13620027356      cpu_core/cycles/                 #    4.769 GHz
33907381511      cpu_core/instructions/           #   11.873 G/sec
1701481151      cpu_core/branches/               #  595.806 M/sec
19152      cpu_core/branch-misses/          #    6.706 K/sec

2.856294128 seconds time elapsed

2.856142000 seconds user
0.000000000 seconds sys
Я попробовал как Clang, так и GCC, то же самое происходит (используется Clang ++ -20 T.cpp -ot -O3 -march = haswell и g ++ -14 t.cpp -ot -O3 -march = Haswell )
Вот моя тестная программа (примечание, это не готовая версия, dot_product () только работает Правильно, если длина равен раза 64):

Код: Выделить всё

#include 
#include 
#include 

inline __m128 horizontal_sum_8(__m256 v) {
__m128 t = _mm_add_ps(_mm256_castps256_ps128(v), _mm256_extractf128_ps(v, 1));
t = _mm_add_ps(t, _mm_movehl_ps(t, t));
return _mm_add_ps(t, _mm_movehdup_ps(t));
}

float dot_product(int length, const float *x, const float *y) {
__m256 sum0 = _mm256_setzero_ps();
__m256 sum1 = _mm256_setzero_ps();
__m256 sum2 = _mm256_setzero_ps();
__m256 sum3 = _mm256_setzero_ps();
int i = 0;
while (i 
Это использует 4 векторных аккумуляторов.  Задержка P-CORE Older Lake x Продукт пропускной способности 4C x 2/C = 8 FMA в полете.  (https://uops.info/).  Каждый FMA кормит 2 нагрузками.   Пропускная способность нагрузки P-Core составляет 3 на часы, поэтому 1,5 FMA на часы является теоретической пиковой пропускной способностью для этого, но только с четырьмя цепочками зависимости он может в среднем только 1 FMA/часы, за исключением случаев, когда он может найти параллелизм уровня инструкции между концом один точечный продукт и начало следующего.  Почему это так непоследовательно?  Что может быть объяснением этой проблемы?  Какой счетчик CPU PERF может показать причину? 3,4 ГГц , чтобы исключить возможность автоматического детерпения, запустить программу ~ 600 раз и создал график рассеяния. Похоже, что время выполнения имеет два типичных значения, ~ 3,4 сек и ~ 4,2 с. В ~ 60% случаев эти два значения являются результатом (я имею в виду, это время, проведенное в программе). В остальном ~ 40%значения между:
        < /p>
Редактировать 2: < /p>
Мне удалось запустить perf record < /code>, не уверен, что это полезно. Левая сторона, когда бег медленная, правая быстро. Числа перед каждой инструкцией -количество образцов Perf Record 
(я использовал циклы ref Record -e: PPP при 4 кГц). Сумма образцов составляет 16130 (левая, медленная) и 12750 (справа, быстро):


Подробнее здесь: https://stackoverflow.com/questions/793 ... erent-runs
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»