2015-03-22 2 views
2

Используя GCC, вы можете сделать что-то вроде этого.Можно ли предположить, что фиксированный размер memcpy оптимизирован?

void foo(MyStruct *a, const MyStruct *b) 
{ 
    memcpy(&a[0], b, sizeof(*a)); 
    memcpy(&a[1], b, sizeof(*a)); 
    memcpy(&a[2], b, sizeof(*a)); 
} 

При написании переносимого кода, используя современные компиляторы C *, это может оптимизировать для вывода такой же, как asm ...

void foo(MyStruct a[3], const MyStruct *b) 
{ 
    a[0] = *b; 
    a[1] = *b; 
    a[2] = *b; 
} 

Мой вопрос, есть ли смысл предполагать вызов функции на memcpy будет всегда быть оптимизирован?

Я прошу об этом, потому что я рассматривал возможность использования memcpy в макросе, который получает экземпляр много раз с размером, известным во время компиляции. Если это вызовет memcpy на некоторых платформах, я бы предпочел не называть его вообще. например: Implement generic swap macro in C


* современные компиляторы C (GCC/Clang/MSVC/ICC). со стандартным/безопасным уровнем оптимизации.

+2

. А почему бы вам просто не написать 'a [0] = * b;' и т. Д. В функции/макросе –

+0

В приведенном примере обязательно, но этот макрос подкачки использует, например, memcpy, http://stackoverflow.com/a/3982430/432509 - зная, что это то, чего следует избегать или нет, полезно. – ideasman42

+0

Вы все равно можете присвоить значение массива, если оно завершено внутри структуры. (может помочь, может не так) – Leushenko

ответ

0

Функция memcpy является очень широкой функцией, которая принимает в качестве входных параметров параметры void *.

От ИСО/МЭК 9899: 1999 (С99):

Сводка:

недействительными * тетсру (недействительными * ограничение s1, сопзЬ пустота * ограничение s2, size_t п);

Описание:

В тетсру функция копирует п символов из объекта, на который указывает s2 в объект, на который указывает s1. Если копирование происходит между перекрывающимися объектами, поведение не определено.

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

Но опять-таки из §6.7.3.1 Формального определения ограничения:

Переводчика может игнорировать или все алиасинг последствие использования ограничения.

Предполагает, что, возможно, не все оптимизирующие компиляторы распознают флаг напрямую. В этом случае memcpy будет работать над (с точки зрения компилятора) возможными дублирующими/перекрывающимися областями памяти и не сможет сделать вывод функциональной эквивалентности a[0] = *b, так как это может также изменять значение b.

Стандарты могут быть изменены в C11, но я не копия этого, так что я не могу сказать ...

Edit:

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

+0

[Проект N1570] (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) почти идентичен к стандарту C11. –

3

Некоторые наивные компиляторы C (например, tinycc) не очень оптимизируют и не будут оптимизировать звонки на memcpy; но они производят столь медленный код, что никто не заботится о производительности двоичного кода, будет использовать их.

Тем не менее, хорошая причина для использования tcc может быть, когда вы не заботитесь вообще о производительности во время выполнения, но все равно много о том, крошечного компилятора может компилировать быстро

Теоретически optimization не обязателен по стандарту C99 или C11 (даже реального или виртуального компьютера не требуется: вы можете запустить стандартную программу C с кучей человеческих подчиненных, но это неэтично, ненадежно и неэффективно). И стандарт C99 не требует компилятора; он может быть наивным интерпретатором и по-прежнему быть стандартной соответствующей реализацией.

На практике, любой серьезный C компилятор, когда просят оптимизировать, позволит оптимизировать ваши звонки memcpy

Смотрите также this answer on Programmers.

Так что я хотел бы использовать memcpy как вы делаете, но документально подтвердить, что современный C оптимизации компилятора, как ожидается, (и, возможно, рекомендуют недавних версий компиляторов как GCC 4.8, по крайней мере, или Clang 3.4, по крайней мере)

Смежные вопросы