LINUX.ORG.RU

Копирование перекрывающихся участков памяти


0

1

Сейчас с коллегой дискутировали о реализации копирования перекрывающихся областей памяти. Ес-но нужно сделать как быстрее и более безглючно.

Участки перекрываются так:

 1.      |----------|
 2. |----------|
Нужно перенести данные из 1 в 2. Стандартными функциями пользоваться в принципе можно, но это слишком большая надежда, что она всегда будет копировать от начала к концу, а не наоборот.

Я предложил обычный цикл for, тупо скопировать из 1 в 2 побайтно. Коллега говорит, что лучше вычислить кусок до перекрытия, скопировать его стандартной функцией, потом докопировать остальное опять же стандартной функцией. Типа говорит, что так будет быстрее несмотря на усложнение алгоритма.

Действие происходит в ядре Linux. Куски памяти могут быть до 15 Мб.

Как считаете, как будет быстрее? Есть ли еще какой-то путь? Заранее спасибо за участие.

★★★★★

Стандартными функциями пользоваться в принципе можно

Это какими?

Можно сделать на ассемблерной вставке. Наверняка быстрее будет. Хотя, чем черт не шутит: gcc -O3 иногда очень даже хорошо оптимизирует.

Eddy_Em ☆☆☆☆☆ ()

1 в 2 по байтно.

А данные не выровнены?

Galant ()
Ответ на: комментарий от hibou

Вспомни шутку про идиотов, использовавших memcpy, не читая внимательно мануала. Помнится, какая-то адобовская ненужная поделка из-за этого отличненько сегфолтилась.

А для копирования памяти блоками наверняка ведь есть ассемблерные функции, которые будут явно шустрее побайтного копирования.

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от Eddy_Em

Да циклом-то не хуже можно скопировать.
Но опять же для разных процев можно по разному.
Например 16-байтовыми кусками с помощью xmm.

Galant ()
Ответ на: комментарий от Galant

У меня такое подозрение (в кодах glibc ковыряться нет желания), что memmove и реализован через ассемблерные архитектурнозависимые инструкции.

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от Galant

Да, видел. Наверно через нее и лучше. У нас еще NULL'ы могут быть. Их тоже переносить нужно, не останавливаясь. Перенесет?

hibou ★★★★★ ()

Было столько срачей на тему memcpy/memmove, где был ты?

/**
* memmove - Copy one area of memory to another
* @dest: Where to copy to
* @src: Where to copy from
* @count: The size of the area.
*
* Unlike memcpy(), memmove() copes with overlapping areas.
*/
void *memmove(void *dest, const void *src, size_t count)

ttnl ★★★★★ ()

> Действие происходит в ядре Linux. Куски памяти могут быть до 15 Мб.

Весьма вероятно, что вы что-то делаете не так. Какой сценарий?

Rzhepish ()
Ответ на: комментарий от Eddy_Em

Кстати, интересно, как будет вести себя memmove, если области перекрываются сильно (т.е. начальная область неперекрытия меньше размера блока).

Нормально будет себя вести. Все кривые случаи в ней предусмотрены. Это стандартная функция.

ttnl ★★★★★ ()
Ответ на: комментарий от Eddy_Em

Ты еще и ман не читаешь :) Стандартная ф-ция memmove весьма медленная, т.к. используется третий участок памяти, и копирование for'ом будет быстрее :).

Jetty ★★★★★ ()

Может проще написать прототип 2х вариантов, скомпилить и посмотреть скорость на деле?

Deleted ()
Ответ на: комментарий от Deleted

Ну если он это делает в ядре, то это не так уж и просто :)

Jetty ★★★★★ ()
Ответ на: комментарий от Jetty

Ты еще и ман не читаешь :) Стандартная ф-ция memmove весьма медленная, т.к. используется третий участок памяти, и копирование for'ом будет быстрее :).

4.2 и бан тебе, переводчик хренов.

Galant ()
Ответ на: комментарий от Jetty
void *memmove(void *dest, const void *src, size_t count)
{
    char *tmp;
    const char *s;

    if (dest <= src) {
        tmp = dest;
        s = src;
        while (count--)
            *tmp++ = *s++;
    } else {
        tmp = dest;
        tmp += count;
        s = src;
        s += count;
        while (count--)
            *--tmp = *--s;
    }
    return dest;
}

Код из ядра linux.

stack_protector ()
Ответ на: комментарий от Galant

поясняю: в мане написано «as though»
Сырцы не смотрел, но уверен что там нет третьего участка. Ядро люди не глупей меня делают небось.

Galant ()

открыть сырцы libc и сделать так как тебе нужно.

visual ★★★ ()
Ответ на: комментарий от Jetty

Ты еще и ман не читаешь :) Стандартная ф-ция memmove весьма медленная, т.к. используется третий участок памяти, и копирование for'ом будет быстрее :).

Какой нах третий участок? Ты чем ударился?

Waterlaz ★★★★ ()
Ответ на: комментарий от Jetty

Стандартная ф-ция memmove весьма медленная, т.к. используется третий участок памяти, и копирование for'ом будет быстрее

Слов нет. Кто ж нарожал-то вас таких, горе-оптимизаторов? Ты действительно уверен, что код ключевых библиотек написан хуже, чем ты, криворучка for-овая, за 5 минут на коленке нафигачишь?

Покажи, блин, где тут «третий участок памяти»:

http://www.mirrorservice.org/sites/ftp.gnu.org/gnu/glibc/glibc-2.14.1.tar.gz/...

Manhunt ★★★★★ ()

А копировать куски памяти от конца к началу реально?

TheKnight ★★ ()
Ответ на: комментарий от Jetty

В выделенном тобой предложении ты не обратил внимания на словосочетание «as though», которое переводится, как «если бы, (как) будто бы, словно, как бы».

Если уж читать man-ы, то внимательно.

OldFatMan ()
Ответ на: комментарий от stack_protector

Я знаю что это за слово. Вот только смысл в том что копирование происходит в два этапа.

Jetty ★★★★★ ()
Ответ на: комментарий от Eddy_Em

А для копирования памяти блоками наверняка ведь есть ассемблерные функции, которые будут явно шустрее побайтного копирования.

есть такие инструкции, rep movsb/rep movsd для копирования блоков, со времен, кажетсяб 486. Но т.к компиляторы ЯВУ таких инструкций не генерируют, а на ассемблере мало кто пишет, инженеры Intel дооптимизировались до того, что обычный mov в цикле, выдаваемый компиляторами, работает быстрее )

Harald ★★★★★ ()
Ответ на: комментарий от Jetty

"...копирование происходит так, как будто бы (как если бы) байты в src сначала копируются в (некоторый) временный массив, который не пересекается ни с src, ни с dst, а затем те же байты копируются из этого временного массива в dst."

«as though» относится ко всей второй части предложения.

Упоминание «двух этапов» тоже воображаемое, как и «временный массив».

OldFatMan ()
Ответ на: комментарий от Jetty

Эпичный фейл. Иди уже подучи английский и не позорься.

geekless ★★ ()
Ответ на: комментарий от stack_protector

Я видел :)
Кстати в ядре это реализуется ассемблером а не вызовом из string.c

Jetty ★★★★★ ()
Ответ на: комментарий от Jetty

Не видишь что ль по аватарке? Твой дальный предок, пришел тебя стыдить, ибо даже обезьяны ржут с твоих комментов.

geekless ★★ ()
Ответ на: комментарий от geekless

Аватарок не вижу.
А ты чтоль обезьяна? Ну тогда мне не интересно с тобой, на этом, думаю, диалог окончен.

Jetty ★★★★★ ()

memmove во все поля, иначе натрахаетесь.

Dark_SavanT ★★★★★ ()
Ответ на: комментарий от Jetty

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

maloi ★★★★★ ()
Ответ на: комментарий от maloi

в моем так же. Но на самом деле так не происходит в умолчательном memmove :). Но есть еще архитектуро спецефические меммувы, которые писаны на асме, а я с асмом не дружу :)

Jetty ★★★★★ ()
Ответ на: комментарий от Jetty

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

hibou ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.