раунд намного медленнее, чем пол / потолок / int в LLVM - PullRequest
0 голосов
/ 28 декабря 2018

Я тестировал некоторые важные подпрограммы, выполняя циклы, такие как:

float *src, *dst;
for (int i=0; i<cnt; i++) dst[i] = round(src[i]);

Все с целью AVX2, новейшим CLANG.Интересно, что floor (x), ceil (x), int (x) ... все кажется быстрым.Но round (x) кажется чрезвычайно медленным и, глядя на разборку, вместо более новых версий SSE или AVX есть какой-то странный код спагетти.Даже когда блокируется возможность векторизации циклов путем введения некоторой зависимости, раунд примерно в 10 раз медленнее.Для пола и т. Д. Сгенерированный код использует vroundss, для раунда - код спагетти ... Есть идеи?

Редактировать: я использую -ffast-math, -mfpmath = sse, -fno-math-errno, -O3, -std = c ++ 17, -march = core-avx2 -mavx2 -mfma

Ответы [ 2 ]

0 голосов
/ 29 декабря 2018

Проблема в том, что ни один из режимов округления SSE не определяет правильное округление для round:

Эти функции округляют x до ближайшего целого числа, но округляют на полпути случаи от нуля (независимо оттекущее направление округления, см. fenv (3)), вместо ближайшего четного целого числа, например rint (3).

Если вы хотите более быстрый код, вы можете попробовать протестировать rint вместо round, поскольку это указывает режим округления, который поддерживается SSE.

0 голосов
/ 28 декабря 2018

Следует отметить, что выражение типа floor(x + 0.5), хотя и не имеет точно такой же семантики, что и round(x), является допустимой заменой почти во всех случаях использования, и я сомневаюсь, что оно примерно в 10 раз медленнее, чем floor(x).

...