Подсказки компилятору
От: maks1180  
Дата: 13.11.22 22:29
Оценка:
Посмотрел я как gcc v10.2 компилирует в ассемблер функцию memcpy на x64 платформе, видел 2 реализации:
1) простая через rep movsb — отличная вещь для копирования небольшого размера
2) сложная, сравнивает размер если size>=8 то копирует 8 байт, потом выравнивается и по 8 байт в цикле копирует, если >=4 то другая ветка срабатывает, если >=2 то третья ветка, если <2 то четвёртая. Код получается большой, но оправдан если нужно скорость и данных много

По какому принципу gcc выбирает если размер не известен на этапе компиляции — мне не понятно. Но очевидно что разработчик может знать в каком месте ожидается много байт, а каком 0-3 байта будет. И если разработчик сможет как-то подсказать компилятору, то код будет меньше и быстрее работать.

Может я что-то не знаю и есть способ как подсказать компилятору ?


По мне так, это должен процессор делать по команде rep movsb если видит скажем что мы просим 17 байт скопировать, он сам должен решить что быстрее будет копировать 8+8+1, чем 17*1. И сам должен решить когда выровняться скажем 1+8+8 или 8+8+1 или 3+8+6.
Неужели современные процессоры этого не делают и компилятору приходится такой код ужастный компилировать, который будет увеличивать размер exe и тормозить при малых размерах копирования ( я про вариант 2)
===============================================
(реклама, удалена модератором)
Отредактировано 13.11.2022 22:46 maks1180 . Предыдущая версия . Еще …
Отредактировано 13.11.2022 22:45 maks1180 . Предыдущая версия .
Отредактировано 13.11.2022 22:36 maks1180 . Предыдущая версия .
Re: Подсказки компилятору
От: Zhendos  
Дата: 14.11.22 11:58
Оценка:
Здравствуйте, maks1180, Вы писали:

M>Посмотрел я как gcc v10.2 компилирует в ассемблер функцию memcpy на x64 платформе, видел 2 реализации:


Непонятно что и где вы смотрели. Но у gcc и clang есть понятие "built-in functions",
в частности "__builtin_memcpy", если компилятор понимает что размер функции известен
во время компиляции то происходит замена memcpy на __builtin_memcpy,
а потом __builtin_memcpy заменяется на конкретную в зависимости
от размер копируемого объекта и опций компилятора, в теории "__builtin_memcpy"
компилятор может обратно заменить на вызов "memcpy" из libc, если код компилируется
оптимизацией по размеру, на какой-нибудь экзотической архитектуре.

И нужно заметить что и memcpy из glibc тоже имеет не самую простую реализацию,
и в зависимости от доступных расширений процессора на котором выполняется могут
быть задействованы разные реализации memcpy с использование SSE2, SSE4.2 и так далее.
Re: Подсказки компилятору
От: kov_serg Россия  
Дата: 14.11.22 12:46
Оценка:
Здравствуйте, maks1180, Вы писали:

M>По мне так, это должен процессор делать по команде rep movsb если видит скажем что мы просим 17 байт скопировать, он сам должен решить что быстрее будет копировать 8+8+1, чем 17*1. И сам должен решить когда выровняться скажем 1+8+8 или 8+8+1 или 3+8+6.

M>Неужели современные процессоры этого не делают и компилятору приходится такой код ужастный компилировать, который будет увеличивать размер exe и тормозить при малых размерах копирования ( я про вариант 2)
Некоторые процессоры делают, а некоторые нет.
Re: Подсказки компилятору
От: watchmaker  
Дата: 14.11.22 13:01
Оценка: 2 (1) +2
Здравствуйте, maks1180, Вы писали:

M>Но очевидно что разработчик может знать в каком месте ожидается много байт, а каком 0-3 байта будет. И если разработчик сможет как-то подсказать компилятору, то код будет меньше и быстрее работать.

M>Может я что-то не знаю и есть способ как подсказать компилятору ?
Подсказывать ты можешь:
И ещё есть несколько вариаций.
Но, как видно, это всё специфичные для компилятора средства, причём ещё и работающие чуть по разному (в части обработки побочных эффектов, например).

В чистом С++ ты можешь только писать код так, чтобы невероятные ветки кода содержали очевидные UB, чтобы компилятор мог честно их игнорировать. Выглядит такой стиль как defensive programming наоборот . Не советую так писать: надо будет предельно аккуратно выписывать все условия, чтобы программу не разнесло тут же




А если под подсказками понимать подсказки, которые могут оказаться неверными, то так на самом деле тоже можно делать.
В C++ есть атрибуты [[likely]] и [[unlikely]], которыми можно помечать соответствующие ветки кода. Тогда компилятор будет будет в первую очередь их оптимизировать, но не ломать возможные альтернативы.
Ну и конечно же, есть соответствующие компилятоспецифичные расширения вроде __builtin_expect, __builtin_expect_with_probability, __builtin_unpredictable и т.д.
Отредактировано 14.11.2022 13:19 watchmaker . Предыдущая версия .
Re[2]: Подсказки компилятору
От: maks1180  
Дата: 14.11.22 14:40
Оценка:
M>>По мне так, это должен процессор делать по команде rep movsb если видит скажем что мы просим 17 байт скопировать, он сам должен решить что быстрее будет копировать 8+8+1, чем 17*1. И сам должен решить когда выровняться скажем 1+8+8 или 8+8+1 или 3+8+6.
M>>Неужели современные процессоры этого не делают и компилятору приходится такой код ужастный компилировать, который будет увеличивать размер exe и тормозить при малых размерах копирования ( я про вариант 2)
_>Некоторые процессоры делают, а некоторые нет.

Чуть подробнее можно ?
===============================================
(реклама, удалена модератором)
Re: Подсказки компилятору
От: Videoman Россия https://hts.tv/
Дата: 14.11.22 17:22
Оценка:
Здравствуйте, maks1180, Вы писали:

M>Может я что-то не знаю и есть способ как подсказать компилятору ?


Есть один очень тупой способ. Поскольку не понятно, что значит небольшие буфера, то вот :
switch (buffer_size)
{
case 0: std::memcpy(dst, src, 0); break;
case 1: std::memcpy(dst, src, 1); break;
case 2: std::memcpy(dst, src, 2); break;
// ...
case 64: std::memcpy(dst, src, 64); break;
// ... as you wish
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.