Я профилирую некоторый код C ++ с perf
и я вижу что __scalbnf
а также __wrap_scalbnf
занимают хороший кусок времени выполнения. Я посмотрел, что это за функции, и я думаю, что я вызываю их через вызов std::exp
, Однако я хотел бы быть в состоянии подтвердить это. Есть ли место, где я могу увидеть код C ++, реализующий std :: exp, чтобы подтвердить это? Или каков наилучший способ для меня (любителя C ++) начать копаться в этом и понимать, что происходит?
Спасибо.
Установить точку останова на __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.
Чтобы подтвердить это std::exp
является причиной __scalbnf
а также __wrap_scalbnf
Вы можете заменить std::exp
звонки либо:
Тогда, если вы все еще видите __scalbnf
а также __wrap_scalbnf
в выводе профилировщика это означает, что он не исходит от std :: exp.