Подтвердить что ты не робот

Как работает внутренняя реализация memcpy?

Как работает стандартная функция C memcpy? Он должен скопировать (большую) часть ОЗУ в другую область в ОЗУ. Поскольку я знаю, что вы не можете двигаться прямо из ОЗУ в ОЗУ в сборке (с инструкцией mov), поэтому я предполагаю, что при копировании он использует регистр CPU в качестве промежуточной памяти?

Но как он копируется? Блоками (как бы они копируются блоками?), Отдельными байтами (char) или самым большим типом данных, который у них есть (копия в длинном длинном двойном - что составляет 12 байтов в моей системе).

EDIT: Хорошо, видимо, вы можете напрямую перемещать данные из ОЗУ в ОЗУ.. Я не эксперт по сборке, и все, что я узнал о сборке, из этого документа (Руководство по сборке X86), в котором упоминается раздел о команде mov, которую вы не можете перенести из ОЗУ в ОЗУ. По-видимому, это не так.

4b9b3361

Ответ 1

Зависит. В общем, вы не могли бы физически копировать что-либо большее, чем самый большой полезный регистр за один цикл, но это не так, как работают машины в эти дни. На практике вы действительно заботитесь о том, что делает процессор, и о характеристиках DRAM. Иерархия памяти машины будет играть решающую роль при выполнении этой копии самым быстрым способом (например, загружаете ли вы целые строки кэша? Каков размер строки DRAM в отношении операции копирования?). Вместо реализации вместо этого можно использовать какие-либо векторные инструкции для реализации memcpy. Без ссылки на конкретную реализацию он эффективно представляет собой байтовую копию с одноместным буфером.

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

Ответ 2

Реализация memcpy очень специфична для системы, в которой она реализована. Реализации часто оказываются аппаратными.

Команды mov-to-memory mov не так уж необычны - они были вокруг с по крайней мере PDP-11 раза, когда вы могли написать что-то вроде этого:

    MOV FROM, R2
    MOV TO,   R3
    MOV R2,   R4
    ADD LEN,  R4
CP: MOV (R2+), (R3+) ; "(Rx+)" means "*Rx++" in C
    CMP R2, R4
    BNE CP

Прокомментированная строка примерно эквивалентна C

*to++ = *from++;

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

Ответ 3

Тривиальная реализация memcpy:

 while (n--) *s2++ = *s1++;

Но glibc обычно использует некоторые умные реализации в коде сборки. memcpy вызовы обычно встраиваются.

На x86 код проверяет, является ли параметр размера литералом, кратным 2 или кратным 4 (используя gcc встроенные функции), и использует цикл с инструкцией movl (copy 4 байты), иначе он вызывает общий случай.

В общем случае используется блок быстрого копирования блоков с помощью инструкций rep и movsl.