Я пытаюсь добиться максимальной пропускной способности с плавающей запятой для вычислений SIMD FMA при загрузке входных данных. Я загружаю столько данных, сколько позволяет относительная скорость загрузки вычислений/памяти. Я также применил буферизацию, чтобы избежать немедленных зависимостей данных, но это тоже не помогло. К сожалению, пропускная способность снижается в два раза.
Рассмотрим следующую функцию FMA:
std::pair fmadd_256(const float* aptr, const float* bptr,
uint64_t sz, uint32_t num_loads) {
constexpr size_t num_lanes = 256 / sizeof(float);
__m256 c[8];
__m256 a[2][num_loads];
__m256 b[2][num_loads];
load_buffer(aptr, bptr, a[0], b[0], 0);
for (uint64_t i = 0; i < sz; i++) {
uint64_t curr_buffer = i % 2;
__m256* curra = a[curr_buffer];
__m256* currb = b[curr_buffer];
if (i < sz - 1) {
uint64_t next_buffer = (i + 1) % 2;
__m256* nexta = a[next_buffer];
__m256* nextb = b[next_buffer];
uint64_t load_position = (i + 1) * num_lanes * num_loads;
load_buffer(aptr, bptr, nexta, nextb, load_position);
}
c[0] = _mm256_fmadd_ps(curra[0], currb[0], c[0]);
c[1] = _mm256_fmadd_ps(curra[0], currb[0], c[1]);
c[2] = _mm256_fmadd_ps(curra[0], currb[0], c[2]);
c[3] = _mm256_fmadd_ps(curra[0], currb[0], c[3]);
c[4] = _mm256_fmadd_ps(curra[1], currb[1], c[4]);
c[5] = _mm256_fmadd_ps(curra[1], currb[1], c[5]);
c[6] = _mm256_fmadd_ps(curra[1], currb[1], c[6]);
c[7] = _mm256_fmadd_ps(curra[1], currb[1], c[7]);
}
constexpr size_t num_unrolls = 8;
uint64_t flops{num_unrolls * num_lanes * 2 * sz};
float res = epilogue(c);
return {res, flops};
}
При выполнении приведенного выше кода я получаю соотношение около 60 гигафлопс/сек, но мой компьютер может достичь скорости 130 гигафлопс/сек. При отключении загрузки памяти код достигает скорости 120 GFLOPS/сек. Я использовал процессор Alderlake. По данным Intel Advisor, необходимое соотношение нагрузки вычислений/памяти для достижения пиковой пропускной способности составляет 4,4 с учетом скорости DRAM.
Что я могу сделать, чтобы повысить производительность программы?< /p>
Интересно, что буферизация не улучшает производительность программы. При загрузке данных в используемый буфер (установка uint64_t next_buffer = i % 2) код выполняется так же быстро, как при циклическом обходе двух буферов. Я также мог бы использовать выровненные векторы вместо невыровненных векторов или переписать код, чтобы избежать ветвления внутри цикла, но я сомневаюсь, что это основная причина относительно медленной программы.
Полно Программа
Полная программа теста приведена ниже:
#include
#include
#include
#include
#include
#include
#include
#include
inline float hadd(__m256 v8) {
__m128 v = _mm256_extractf128_ps(v8, 1);
v = _mm_add_ps(v, _mm256_castps256_ps128(v8));
v = _mm_add_ps(v, _mm_movehl_ps(v, v));
v = _mm_add_ss(v, _mm_movehdup_ps(v));
return _mm_cvtss_f32(v);
}
float epilogue(__m256 c[8]) {
c[0] = _mm256_add_ps(c[0], c[1]);
c[2] = _mm256_add_ps(c[2], c[3]);
c[4] = _mm256_add_ps(c[4], c[5]);
c[6] = _mm256_add_ps(c[6], c[7]);
c[0] = _mm256_add_ps(c[0], c[3]);
c[4] = _mm256_add_ps(c[4], c[6]);
c[0] = _mm256_add_ps(c[0], c[4]);
float res = hadd(c[0]);
return res;
}
template
void reporting(T duration, double flops, float res) {
float gflops_sec = (flops * 1000.0) / duration;
std::cout
Подробнее здесь: https://stackoverflow.com/questions/785 ... le-maintai
Как добиться максимальной производительности FMA при использовании входных данных (при сохранении требуемого соотношения ⇐ C++
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Как добиться максимальной производительности в отношениях «многие ко многим»?
Anonymous » » в форуме Php - 0 Ответы
- 28 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Как добиться максимальной производительности в отношениях «многие ко многим»? [закрыто]
Anonymous » » в форуме Php - 0 Ответы
- 36 Просмотры
-
Последнее сообщение Anonymous
-