Ассемблер: memcpy (В чем подвох?)

Модератор: Модераторы разделов

BratSinot
Сообщения: 812
ОС: Slackware64

Ассемблер: memcpy

Сообщение BratSinot »

Доброго времени суток!

Я тут написал свою memcpy(для amd64):

Код: Выделить всё

void memcpy(void *to, const void *from, size_t count)
{
 asm("cld\n\t"
 "xchg %rcx, %rdx\n\t"
 "rep movsb\n\t");
}


Насколько я знаю, в glibc memcpy имеет различные оптимизированые версии с mmx, sse и т.п., отсюда я предпологаю что оно больше( по коду) моего варианта. Собственно вопрос, в чем подвох? Почему не использовать мой вариант?
Спасибо сказали:
Аватара пользователя
taaroa
Сообщения: 1319

Re: Ассемблер: memcpy

Сообщение taaroa »

BratSinot писал(а):
17.09.2011 15:12
Собственно вопрос, в чем подвох? Почему не использовать мой вариант?

mailto: libc-alpha@sourceware.org
:wq
Спасибо сказали:
frp
Сообщения: 1445
ОС: Debian Squeeze

Re: Ассемблер: memcpy

Сообщение frp »

BratSinot писал(а):
17.09.2011 15:12
Насколько я знаю, в glibc memcpy имеет различные оптимизированые версии с mmx, sse и т.п., отсюда я предпологаю что оно больше( по коду) моего варианта. Собственно вопрос, в чем подвох? Почему не использовать мой вариант?

Например, потому, что он медленнее glibc-ового.
Спасибо сказали:
Аватара пользователя
Nazyvaemykh
Сообщения: 438
Статус: Подопытный участник

Re: Ассемблер: memcpy

Сообщение Nazyvaemykh »

А в чем проблема:
1. сравнить по скорости выполнения, по числу команд, по числу всяко разных кеш-промахов и пр.
2. сравнить сам код.
¡ Страсть к разрушению есть творческая страсть!
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: Ассемблер: memcpy

Сообщение BratSinot »

frp писал(а):
17.09.2011 16:40
BratSinot писал(а):
17.09.2011 15:12
Насколько я знаю, в glibc memcpy имеет различные оптимизированые версии с mmx, sse и т.п., отсюда я предпологаю что оно больше( по коду) моего варианта. Собственно вопрос, в чем подвох? Почему не использовать мой вариант?

Например, потому, что он медленнее glibc-ового.

А почему? Да и потом, есть -Os.
Спасибо сказали:
Аватара пользователя
Nazyvaemykh
Сообщения: 438
Статус: Подопытный участник

Re: Ассемблер: memcpy

Сообщение Nazyvaemykh »

намекну, что у современных процессоров есть кеш, при чем несколько уровней этого кеша.
как только происходнит обращения к памяти, которой нет в L2, теряются десятки циклов процессора. каким образом свести эти потери до минимума? я этого не знаю, а Ульрих Дреппер — знает.
ваш код наивным образом никак не учитывает это вообще.
¡ Страсть к разрушению есть творческая страсть!
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Ассемблер: memcpy

Сообщение NickLion »

BratSinot, вообще-то есть много сайтов, где эта тема разжёвана всеми доступными способами, например, wasm.ru.
Кратко почему не использовать Ваш вариант? Да потому что movsb. Операции над байтами в памяти процессор делает неэффективно. Операция записи одного байта = считать блок, заменить байт, записать блок. Ассемблер абстрагирует от этого (потому что CISC), но тем не менее время всё равно тратится
Например, считать сразу 4/8 байт (выровненных) по времени занимает столько же, сколько и один байт. Так почему не читать/писать сразу группами? В этом и состоит ускорение всех memcpy/memmove.
Спасибо сказали:
frp
Сообщения: 1445
ОС: Debian Squeeze

Re: Ассемблер: memcpy

Сообщение frp »

BratSinot писал(а):
17.09.2011 16:49
А почему?

Если уж не учитывать особенности кэша и конкретных процессоров, то, как минимум, из-за тормозности movsb - нужно пересылать не по байту, а по максимально возможному куску (по 8 байт).
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: Ассемблер: memcpy

Сообщение BratSinot »

NickLion, frp хрен с ним, со скоростью разобрались, а что насчет размера?
Спасибо сказали:
frp
Сообщения: 1445
ОС: Debian Squeeze

Re: Ассемблер: memcpy

Сообщение frp »

BratSinot писал(а):
17.09.2011 20:17
NickLion, frp хрен с ним, со скоростью разобрались, а что насчет размера?

На десктопах, на которых овер128 Мб памяти - пофиг. А в embedded, где главное ограничение - размер, glibc-у и так не место.
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: Ассемблер: memcpy

Сообщение BratSinot »

frp писал(а):
17.09.2011 21:54
На десктопах, на которых овер128 Мб памяти - пофиг. А в embedded, где главное ограничение - размер, glibc-у и так не место.

Епрст, а -Os просто так сделан?
Спасибо сказали:
Аватара пользователя
Nazyvaemykh
Сообщения: 438
Статус: Подопытный участник

Re: Ассемблер: memcpy

Сообщение Nazyvaemykh »

-Os — это же флаг компилятора, а не ассемблера.
¡ Страсть к разрушению есть творческая страсть!
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Ассемблер: memcpy

Сообщение drBatty »

BratSinot
епрст - Os на ассемблер не действует. А ваш код == велосипед.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
frp
Сообщения: 1445
ОС: Debian Squeeze

Re: Ассемблер: memcpy

Сообщение frp »

BratSinot писал(а):
17.09.2011 22:53
Епрст, а -Os просто так сделан?

-Os - флаг компилятора, а не ассемблера, и на десктопах, где овер128 Мб памяти и гигабайты дискового пространства, он никому нафиг не нужен, а нужен только в embedded, где glibc никому не нужен :)


На десктопах обычно компилируют с -O2, который наоборот увеличивает размер.
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Ассемблер: memcpy

Сообщение NickLion »

Мне показалось, что BratSinot, говоря о "-Os" имел в виду glibc, а не свой код. Что мол скомпилировать glibc с этим флагом и насколько плох он будет по размеру.
Вообще на embedded системах редко используют тот же glibc - в нём реализовано много функций, 80% которых на этом устройстве не нужна. Да и тот же флаг -Os позволяет применить оптимизации, но не меняет сам алгоритм. А для выиграша размера иногда нужно выбрать другой алгоритм, поэтому и используются различные маленькие библиотечки, которые реализуют может только 20% но так как надо и только то, что надо.
Спасибо сказали:
frp
Сообщения: 1445
ОС: Debian Squeeze

Re: Ассемблер: memcpy

Сообщение frp »

NickLion
Тот же uClibc, несмотря на свою микроскопичность, пытается реализовать большинство нужных функций. Отличается он от glibc-а тем, что его можно собрать без большинства поддерживаемых им функций (ну и реализациями под минимальное использование памяти).
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: Ассемблер: memcpy

Сообщение BratSinot »

Nazyvaemykh писал(а):
17.09.2011 23:02
-Os — это же флаг компилятора, а не ассемблера.

drBatty писал(а):
18.09.2011 07:12
BratSinot
епрст - Os на ассемблер не действует. А ваш код == велосипед.

А мой код для ассемблера написан? Он для C написан.
Спасибо сказали:
frp
Сообщения: 1445
ОС: Debian Squeeze

Re: Ассемблер: memcpy

Сообщение frp »

BratSinot писал(а):
18.09.2011 18:03
А мой код для ассемблера написан? Он для C написан.

Код: Выделить всё

void memcpy(void *to, const void *from, size_t count)
{
asm("cld\n\t"
"xchg %rcx, %rdx\n\t"
"rep movsb\n\t");
}

C здесь только в объявлении функции, реализация - чистый asm.
Спасибо сказали:
hippi90
Сообщения: 83
ОС: Debian testing

Re: Ассемблер: memcpy

Сообщение hippi90 »

А в чем была сложность посмотреть реализацию в glibc и сравнить её со своей? Тем более, что там есть поясняющие комментарии:

Код: Выделить всё

void *
memcpy (dstpp, srcpp, len)
     void *dstpp;
     const void *srcpp;
     size_t len;
{
  unsigned long int dstp = (long int) dstpp;
  unsigned long int srcp = (long int) srcpp;

  /* Copy from the beginning to the end.  */

  /* If there not too few bytes to copy, use word copy.  */
  if (len >= OP_T_THRES)
    {
      /* Copy just a few bytes to make DSTP aligned.  */
      len -= (-dstp) % OPSIZ;
      BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ);

      /* Copy whole pages from SRCP to DSTP by virtual address manipulation,
     as much as possible.  */

      PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len);

      /* Copy from SRCP to DSTP taking advantage of the known alignment of
     DSTP.  Number of bytes remaining is put in the third argument,
     i.e. in LEN.  This number may vary from machine to machine.  */

      WORD_COPY_FWD (dstp, srcp, len, len);

      /* Fall out and copy the tail.  */
    }

  /* There are just a few bytes to copy.  Use byte memory operations.  */
  BYTE_COPY_FWD (dstp, srcp, len);

  return dstpp;
}
Спасибо сказали:
frp
Сообщения: 1445
ОС: Debian Squeeze

Re: Ассемблер: memcpy

Сообщение frp »

hippi90
Приведенный вами код - для 32бит.

PS. BratSinot, ваша сигнатура функции не совпадает с положенной еще. man memcpy - оно должно возвращать указатель на dest.
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: Ассемблер: memcpy

Сообщение BratSinot »

frp писал(а):
18.09.2011 18:54
C здесь только в объявлении функции, реализация - чистый asm.

Сути не меняет, он написан для C. Писал бы я на ассемблере я ни за что бы не стал использовать функцию и раздельную компиляцию.

frp писал(а):
18.09.2011 21:22
PS. BratSinot, ваша сигнатура функции не совпадает с положенной еще. man memcpy - оно должно возвращать указатель на dest.

Ой, пардон, щас исправлю:

Код: Выделить всё

void *memcpy(void *to, const void *from, size_t count)
{
 asm("cld\n\t"
 "xchg %rcx, %rdx\n\t"
 "rep movsb\n\t"
 "xchg %rdi, %rax\n\t");
}


А в чем была сложность посмотреть реализацию в glibc и сравнить её со своей? Тем более, что там есть поясняющие комментарии:

Да и без сравнений понятно, что в glibc код больше, даже если брать со всякими mmx, sse.
Спасибо сказали:
frp
Сообщения: 1445
ОС: Debian Squeeze

Re: Ассемблер: memcpy

Сообщение frp »

BratSinot писал(а):
18.09.2011 21:35
xchg %rdi, %rax

В %rdi в конце будет указатель на память сразу после конца данных в to. А нужно вернуть поинтер на начало.
BratSinot писал(а):
18.09.2011 21:35
Да и без сравнений понятно, что в glibc код больше, даже если брать со всякими mmx, sse.

Смысл на десктопе фапать на размер кода? Особенно во времена, когда десктоп с меньше 128 Мб памяти - это крайне редкое старье, а новые с меньше 1 Гб уже и не делаются. Здесь приоритет быстродействие (в котором ваша реализация сильно проигрвает глибсовой), а не выигрыш в несколько десятков байт.
Спасибо сказали:
BratSinot
Сообщения: 812
ОС: Slackware64

Re: Ассемблер: memcpy

Сообщение BratSinot »

frp писал(а):
18.09.2011 22:53
BratSinot писал(а):
18.09.2011 21:35
xchg %rdi, %rax

В %rdi в конце будет указатель на память сразу после конца данных в to. А нужно вернуть поинтер на начало.

Откуда там конец будет?

frp писал(а):
18.09.2011 22:53
BratSinot писал(а):
18.09.2011 21:35
Да и без сравнений понятно, что в glibc код больше, даже если брать со всякими mmx, sse.

Смысл на десктопе фапать на размер кода? Особенно во времена, когда десктоп с меньше 128 Мб памяти - это крайне редкое старье, а новые с меньше 1 Гб уже и не делаются. Здесь приоритет быстродействие (в котором ваша реализация сильно проигрвает глибсовой), а не выигрыш в несколько десятков байт.

Смысл такой-же, какой и в -Os. Если можно улучшить, значит надо улучшить.
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5427
ОС: Gentoo

Re: Ассемблер: memcpy

Сообщение /dev/random »

BratSinot писал(а):
19.09.2011 07:44
Смысл такой-же, какой и в -Os. Если можно улучшить, значит надо улучшить.

Улучшить? Слегка уменьшить размер ценой значительного снижения скорости? Это вы называете "улучшить"?
Спасибо сказали:
frp
Сообщения: 1445
ОС: Debian Squeeze

Re: Ассемблер: memcpy

Сообщение frp »

BratSinot писал(а):
19.09.2011 07:44
Откуда там конец будет?

Изначально %rdi должен бы указывать в to. Каждый movsb инкрементирует %rdi и %rsi. То есть, когда копирование закончится, %rdi будет указывать в to + count. И вы это вернете вместо просто to.
BratSinot писал(а):
19.09.2011 07:44
Смысл такой-же, какой и в -Os. Если можно улучшить, значит надо улучшить.

Из -Os на десктопе смысл нулевой. А терять из-за нескольких байт производительность в разы - это не улучшение ИМХО.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Ассемблер: memcpy

Сообщение drBatty »

BratSinot писал(а):
18.09.2011 21:35
Сути не меняет, он написан для C.

для чего - как раз не важно. Это написано на асме.
BratSinot писал(а):
19.09.2011 07:44
Смысл такой-же, какой и в -Os. Если можно улучшить, значит надо улучшить.

Почему вы решили, что -Os "улучшает"? Оно обычно всё портит. Улучшает -O3. А размер не имеет никакого значения - даже для HelloWorld.
ЗЫЖ я про нормальные системы, про всякие кофемолки и т.д. - не в курсе. Возможно в кофемолки это и имеет значение, хотя вряд-ли, там наверное сейчас тоже мегабайты ОЗУ.
frp писал(а):
19.09.2011 09:14
Изначально %rdi должен бы указывать в to. Каждый movsb инкрементирует %rdi и %rsi. То есть, когда копирование закончится, %rdi будет указывать в to + count. И вы это вернете вместо просто to.

угу. ИМХО надо в начале push %rdi, а потом pop %rax. тогда будет как надо. Только очень медленно.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Nazyvaemykh
Сообщения: 438
Статус: Подопытный участник

Re: Ассемблер: memcpy

Сообщение Nazyvaemykh »

BratSinot,
раз ужь взялись переписывать libc, не забудьте улучшить qsort. Сортировка пузырьком вместо используемого в glibc громоздкого алгоритма позволит сохранить куда больше памяти, чем улучшение memcpy.
¡ Страсть к разрушению есть творческая страсть!
Спасибо сказали:
frp
Сообщения: 1445
ОС: Debian Squeeze

Re: Ассемблер: memcpy

Сообщение frp »

drBatty писал(а):
19.09.2011 09:22
Улучшает -O3.

Некоторые вещи -O3 наоборот ломает, -O2 безопаснее будет.
Nazyvaemykh писал(а):
19.09.2011 10:18
BratSinot,
раз ужь взялись переписывать libc, не забудьте улучшить qsort. Сортировка пузырьком вместо используемого в glibc громоздкого алгоритма позволит сохранить куда больше памяти, чем улучшение memcpy.

Не получится. И qsort, и бульбашка не требуют дополнительной памяти. А код у qsort-а не сильно длиннее.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Ассемблер: memcpy

Сообщение drBatty »

frp писал(а):
19.09.2011 11:35
Некоторые вещи -O3 наоборот ломает, -O2 безопаснее будет.

с этим я не спорю - -O3 иной раз делает слишком хорошо (:
frp писал(а):
19.09.2011 11:35
Не получится. И qsort, и бульбашка не требуют дополнительной памяти. А код у qsort-а не сильно длиннее.

qsort потребляет O(log(N)) слов стека в среднем, и N^2 в худшем случае. Для пузырька достаточно одного регистра (для данных. +1 для флага).
а код раза в 3 короче, и то, это без оптимизаций. Если вы задумаете каким-то хитрым образом выбирать медиану, то код будет длиннее раз в 10.
Есть за что бороться (:
А ещё есть memmove, которая в последнее время совсем раздулась, да и не работает она с adobeflashplayer - почему её не заменить на простейший аналог из двух rep movsb? (:
Сэкономим Over9000 байтов + будет работать флеш. Ну CPU придётся проапгрейдить до i7, но ведь это мелочь!
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Nazyvaemykh
Сообщения: 438
Статус: Подопытный участник

Re: Ассемблер: memcpy

Сообщение Nazyvaemykh »

drBatty, разве апгрейд CPU сильно поможет? Там же в доступе к памяти затыки, а не CPU?
¡ Страсть к разрушению есть творческая страсть!
Спасибо сказали: