оптимизированный memcpy для данных малого или фиксированного размера в gcc - PullRequest
3 голосов
/ 15 ноября 2010

Я использую memcpy для копирования как данных переменного размера, так и данных фиксированного размера. В некоторых случаях я копирую небольшие объемы памяти (всего несколько байтов). В GCC я вспоминаю, что memcpy был встроенным / встроенным. Однако при профилировании моего кода (с помощью valgrind) я вижу тысячи вызовов самой функции memcpy в glibc.

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

ПРИМЕЧАНИЕ. В большинстве случаев объем копируемых данных доступен как константа времени компиляции.

CXXFLAGS: -O3 -DNDEBUG

Код, который я использую сейчас, заставляет встроенные функции, если вы снимаете префикс _ встроенный , встроенный не используется. Это вызывается из различных других шаблонов / функций, используя T = sizeof (тип). Используемые размеры: 1, 2, кратные 4, несколько размеров 50-100 байт и некоторые более крупные структуры.

template<int T>
inline void load_binary_fixm(void *address)
{
    if( (at + T) > len )
        stream_error();

    __builtin_memcpy( address, data + at, T );
    at += T;
}

1 Ответ

2 голосов
/ 15 ноября 2010

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

Например, где T равно 1, просто назначьте один символ.

Если вы знаете,адреса выровнены, используйте тип int для вашей платформы с соответствующим размером.

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

Точкаэто делается для того, чтобы избежать ветвления и сохранения счетчика.

Если T велико, я был бы удивлен, если бы вы справились лучше, чем библиотека memcpy (), и накладные расходы на вызов функции, вероятно, были бы потеряны вшум.Если вы хотите оптимизировать, посмотрите вокруг реализации memcpy ().Существуют варианты, в которых используются расширенные инструкции и т. Д.

Обновление:

Если посмотреть на ваш актуальный (!) Вопрос о встраивании memcpy, такие вопросы, как версии компилятора и платформы становятся актуальными.Из любопытства вы пробовали использовать std :: copy, что-то вроде этого:

template<int T>
inline void load_binary_fixm(void *address)
{
    if( (at + T) > len )
        stream_error();

    std::copy(at, at + T, static_cast<char*>(address));
    at += T;
}
...