Почему я вижу __scalbnf в моем профайлере?

Я профилирую некоторый код C ++ с perfи я вижу что __scalbnf а также __wrap_scalbnf занимают хороший кусок времени выполнения. Я посмотрел, что это за функции, и я думаю, что я вызываю их через вызов std::exp, Однако я хотел бы быть в состоянии подтвердить это. Есть ли место, где я могу увидеть код C ++, реализующий std :: exp, чтобы подтвердить это? Или каков наилучший способ для меня (любителя C ++) начать копаться в этом и понимать, что происходит?

Спасибо.

0

Решение

Установить точку останова на __scalbn, Запустите вашу программу. Посмотрите на обратный след (в GDB, bt). Дерево вызовов покажет, что exp() является родительской функцией для __scalbn,

Если функция имеет несколько вызывающих, первый удар может не быть из «горячей» функции, которую вы профилируете.

Чтобы выяснить, какая функция высшего уровня (включая ее детей) отвечает за использование большого количества времени, см. linux perf: как интерпретировать и находить горячие точки. При нисходящем профилировании можно найти дорогие функции, которые выполняют всю свою работу при вызове других функций, даже если эти другие функции также имеют «невинных» вызывающих. (например. memcpy интенсивно используется и часто неизбежен, но вы хотели бы найти вызывающих абонентов, которые используют его слишком часто и могут быть оптимизированы лучше. Или вообще не звонил.)


И кстати, да математика Glibc exp() реализация использует внутренне __scalbn, Я не уверен, насколько плоха реализация, но я не вижу версию asm для x86-64, только эту версию на чистом C. https://code.woboq.org/userspace/glibc/sysdeps/ieee754/dbl-64/wordsize-64/s_scalbn.c.html. (За __scalbnl(long double) есть https://code.woboq.org/userspace/glibc/sysdeps/x86_64/fpu/s_scalbnl.S.html, используя x87 fscale инструкция для 80-битных чисел. Но есть только файлы i386 asm для других размеров. И IA-64 (Itanium), но не x86-64).

У glibc есть некоторый векторизованный код EXP, как, например, версия SSE4 SVML https://code.woboq.org/userspace/glibc/sysdeps/x86_64/fpu/multiarch/svml_d_exp2_core_sse4.S.html#_ZGVbN2v_exp_sse4.


Если вы хотите более высокую производительность exp() без идеальной точности, см Быстрая реализация экспоненциальной функции с использованием AVX (это для floatне double, Я забыл, если есть SO ответ с двойной версией).

Также связано: Эффективная реализация log2 (__m256d) в AVX2.

1

Другие решения

Чтобы подтвердить это std::exp является причиной __scalbnf а также __wrap_scalbnfВы можете заменить std::exp звонки либо:

  • тождественная функция, которая возвращает входное значение
  • или альтернативной реализацией exp (например, fm_exp, найден Вот)

Тогда, если вы все еще видите __scalbnf а также __wrap_scalbnf в выводе профилировщика это означает, что он не исходит от std :: exp.

1

По вопросам рекламы [email protected]