Как получить `gcc` для генерации инструкции` bts` для x86-64 из стандартного C? - PullRequest
17 голосов
/ 11 января 2010

Вдохновленный недавним вопросом , я хотел бы знать, знает ли кто-нибудь, как получить gcc для генерации инструкции x86-64 bts (проверка и установка битов) в Linux x86 -64 платформы, без с использованием встроенной сборки или нестандартных встроенных функций компилятора.

Похожие вопросы:

Переносимость для меня важнее, чем bts, поэтому я не буду использовать директиву asm, и если есть другое решение, я предпочитаю не использовать встроенные функции компилятора.

EDIT : исходный язык C не поддерживает атомарные операции, поэтому я не особо заинтересован в получении atomic test-and-set (хотя это и является первоначальной причиной тест-и-установить, чтобы существовать в первую очередь). Если я хочу что-то атомарное, я знаю, что у меня нет шансов сделать это со стандартным C-источником: это должна быть встроенная, библиотечная функция или встроенная сборка. (Я реализовал атомарные операции в компиляторах, которые поддерживают несколько потоков.)

Ответы [ 3 ]

2 голосов
/ 06 марта 2010

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

  • Низкоуровневые драйверы. Однако, если вы пишете тот, который вы, вероятно, знаете ASM, он достаточно привязан к системе, и, вероятно, большинство задержек происходит при вводе / выводе
  • Тестирование на флаги. Обычно это происходит либо при инициализации (только один раз в начале), либо при некоторых общих вычислениях (что занимает гораздо больше времени).

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

Для части Edit - использование только bts не гарантирует элементарность операции. Все это гарантирует, что это ядро ​​будет на этом ядре (так же, как и or сделано в памяти). На многопроцессорных устройствах (необычных) или многоядерных (очень распространенных) вам все равно придется синхронизироваться с другими процессорами.

Поскольку синхронизация намного дороже, я верю, что разница между:

asm("lock bts %0, %1" : "+m" (*array) : "r" (bit));

и

asm("lock or %0, %1" : "+m" (*array) : "r" (1 << bit));

минимально. И вторая форма:

  • Можно установить несколько флагов одновременно
  • Иметь приятную __sync_fetch_and_or (array, 1 << bit) форму (насколько я помню, работает на gcc и intel compiler).
1 голос
/ 11 января 2010

Я использую атомные встроенные функции gcc, такие как __sync_lock_test_and_set (http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html). Изменение флага -march напрямую повлияет на то, что генерируется. Я использую его с i686 прямо сейчас, но http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/i386-and-x86_002d64-Options.html#i386-and-x86_002d64-Options показывает все возможности.

Я понимаю, что это не совсем то, о чем вы просите, но я нашел эти две веб-страницы очень полезными, когда искал подобные механизмы.

0 голосов
/ 11 января 2010

Я считаю (но не уверен), что ни в стандартах C ++, ни в C еще нет механизмов для этих типов механизмов синхронизации. Поддержка механизмов синхронизации более высокого уровня находится в различных состояниях стандартизации, но я даже не думаю, что один из них позволит вам получить доступ к типу примитива, который вам нужен.

Вы программируете структуры данных без блокировок, где блокировок недостаточно?

Вы, вероятно, хотите просто пойти дальше и использовать нестандартные расширения gcc и / или операционные системы или библиотечные примитивы синхронизации. Могу поспорить, что есть библиотека, которая может обеспечить тип переносимости, который вы ищете, если вы заинтересованы в использовании встроенных функций компилятора. (Хотя на самом деле, я думаю, что большинство людей просто кусают пулю и используют специфичный для gcc код, когда им это нужно. Не идеально, но стандарты не соблюдались).

...