2015-01-29 2 views
4

Я отлаживаю транзакционную систему обработки, которая чувствительна к производительности.Что такое __builtin__functions для C++?

Я нашел код, который использует __builtin_memcpy и __builtin_memset вместо memcpy и memset.

Для чего предназначены __builtin_functions? , чтобы предотвратить проблемы с зависимостью в архитектуре или компиляторе?

Или есть ли какая-либо причина в производительности, когда предпочтительны __builtin_functions?

спасибо: D

+4

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

+0

Какой компилятор вы используете? – user763305

+2

В большинстве случаев они бесполезны, и люди используют их по неверным причинам, воображая, что у них есть магические свойства. Если вы не используете '-fno-builtin-memcpy', gcc распознает, что memcpy является стандартной функцией и обрабатывает его так же, как __builtin_memcpy (что может просто излучать вызов функции libc memcpy). –

ответ

2

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

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

int generate_builtin_memcpy(expr arg1, expr arg2, expr size) 
{ 
    if (is_constant(size) && eval(size) < SOME_NUMBER) 
    { 
     ... do magic inline memory copy ... 
    } 
    else 
    { 
     ... call "real" memcpy ... 
    } 
} 

[для настраиваемых компиляторов, там, как правило, одна из этих функций для каждой архитектуры процессора, который имеет различные конфигурации, как в какие условия «реальные» memcpy вызывается, или когда инлайн тетсру используется.]

Ключ здесь в том, что вы МОЖЕТЕ написать свой собственный memcpy, который НЕ основан на __builtin_memcpy(), который ВСЕГДА выполняет функцию и не делает то же самое, что и обычный memcpy [у вас будет немного неприятностей, если вы измените его поведение много, поскольку стандартная библиотека C вероятно, звонит memcpy в нескольких тысячах мест - но, например, делает статистику по тому, сколько раз вызывается memcpy, и какие размеры могут быть копиями одного из таких прецедентов.

Другая важная причина для использования __builtin_* заключается в том, что они предоставляют код, который в противном случае должен был бы быть написан на встроенном ассемблере или, возможно, вообще не доступен программисту. Настройка/получение специальных регистров будет такой.

Есть другие методы, чтобы решить эту проблему, например clang имеет LibraryPass, что предполагает библиотечные вызовы делают общие функции с другими альтернативами, например, так printf гораздо «тяжелее», чем puts, он заменяет соответствующие printf("constant string with no formatting\n") S в puts("constant string with no formatting") и многие тригонометрические и другие математические функции разрешаются в общих простых значений при вызове с константами и т.д.

Вызов __builtin_* непосредственно для функций, таких как memcpy или sin или некоторые такие, вероятно, не то, чтобы сделать - это только делает ваш код менее портативны и вовсе не должны быть быстрее. Вызов __builtin_special_function, когда нет другого, обычно является решением в некоторых сложных ситуациях - но вы, вероятно, должны обернуть его в свою собственную функцию, например.

int get_magic_property() 
{ 
    return __builtin_get_magic_property(); 
} 

Таким образом, когда вы переносите в Windows, вы можете легко сделать:

int get_magic_property() 
{ 
#if WIN32 
    return Win32GetMagicPropertyEx(); 
#else 
    return __builtin_magic_property(); 
#endif 
} 
1

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

http://lwn.net/Articles/29183/

0

__builtin_* функции оптимизированы функции, предусмотренные библиотек компилятора. Это могут быть встроенные версии стандартных библиотечных функций, таких как memcpy и, возможно, более типично некоторые из функций математики.

В качестве альтернативы, они могут быть оптимизированы функциями для типичных задач для этой конкретной цели - например, DSP может иметь встроенные функции FFT

Какие предусмотрены функции, как __builtin_ определяются разработчиками компилятора, и будет описанных в руководствах для компилятора.

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

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

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

#ifdef SOME_CPU_FLAG 
#define MEMCPY __builtin_memcpy 
#else 
#define MEMCPY memcpy