Как управлять компиляцией библиотек C ++ только для заголовков между общими объектами - PullRequest
4 голосов
/ 03 апреля 2019

Я разрабатываю большой программный пакет, состоящий из множества пакетов, которые скомпилированы в общие объекты.Из соображений производительности я хочу скомпилировать Eigen 3 (библиотека только для заголовков) с векторными инструкциями, но шаблонные методы компилируются повсеместно.Как я могу гарантировать, что функции Eigen скомпилированы в определенный объектный файл?

Это программное обеспечение состоит из ~ 2000 отдельных пакетов.Чтобы развитие шло в разумном темпе, рекомендуемый способ компиляции программы состоит в том, чтобы редко проверять некоторые пакеты и компилировать их, после чего программа может выполняться с использованием предварительно скомпилированных (некоторыми системами CI) общих библиотек.

Проблема в том, что часть моей ответственности - оптимизировать процессорное время программы.Для этого я хотел скомпилировать пакет, над которым я работаю (назовем его A.so), с флагом -march, чтобы Eigen мог использовать современные расширения процессора SIMD.

К сожалению, поскольку Eigenбиблиотека только для заголовков, функции Eigen скомпилированы во множество различных общих объектов.Например, одним из наиболее ресурсоемких методов, вызываемых в A.so, является ядро ​​с матричным умножением, которое компилируется в B.so.Многие другие собственные функции скомпилированы в C.so, D.so и т. Д. Так как эти объекты скомпилированы для более старых, более широко реализованных расширений набора команд, они не скомпилированы с AVX, AVX2 и т. Д.

OfКонечно, одним из возможных решений является включение пакетов B, C, D и т. д. в мою собственную разреженную компиляцию, но это сводит на нет преимущество компиляции только части проекта.Кроме того, у меня остается все больше и больше пакетов, если я действительно хочу векторизовать все операции линейной алгебры в коде пакета A.

То, что я ищу, - это способ скомпилировать все Eigen.функции, которые пакет A использует в A.so, как если бы функции Eigen были определены с ключевым словом static.Это возможно?Есть ли какой-то механизм в компиляторе / компоновщике, который я могу использовать, чтобы это произошло?

Ответы [ 2 ]

4 голосов
/ 03 апреля 2019

Одно из очевидных решений - скрыть эти символы.Это происходит (если я правильно понимаю проблему), потому что эти функции экспортируются и могут использоваться другими впоследствии загруженными библиотеками.

Когда вы создаете свою библиотеку и связываетесь с другими библиотеками, компоновщик повторно использует все, что может.И старые пакеты также.Надеюсь, вам не нужны эти библиотеки для вашей собственной сборки?

Итак, два варианта:

  • Принудительная загрузка A перед другими библиотеками (но если вам нужнадругие библиотеки, я не думаю, что это выполнимо),
  • Скажите компоновщику, что эти функции не должны быть видны другим библиотекам (visibility=hidden по умолчанию).

Iчто-то подобное происходило с плохо скомпилированной сторонней библиотекой.Он был построен в режиме отладки, поставлялся в продукте, и одна из наших библиотек внезапно испытала замедление.Файлы карт идентифицировали, откуда появилась функция отладки преступника, так как она экспортировала все свои символы по умолчанию.

1 голос
/ 04 апреля 2019

Альтернативный способ изменить видимость без изменения кода - отфильтровать символы на этапе компоновки с помощью скриптов версии -> https://sourceware.org/binutils/docs/ld/VERSION.html.. Вам понадобится что-то вроде { global: *; local: extern "C++" { Eigen::*; *Eigen::internal::*; }; };

...