Почему я вижу __scalbnf в моем профайлере? - PullRequest
0 голосов
/ 02 июля 2018

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

Спасибо.

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

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

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

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


И, кстати, да, математическая реализация glibc lib 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-разрядных операций с плавающей запятой. Но есть только файлы as38 i386 для других размеров. И 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 .

0 голосов
/ 02 июля 2018

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

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

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

...