DASM 0 21 ноября, 2013 Опубликовано 21 ноября, 2013 · Жалоба 598 */ 599 void *memcpy(void *dest, const void *src, size_t count) 600 { 601 char *tmp = dest; 602 const char *s = src; 603 604 while (count--) 605 *tmp++ = *s++; 606 return dest; 607 } 608 EXPORT_SYMBOL(memcpy); Такой вот сурец из string.c ... видел более оптимизированную версию с раскруткой цикла. Что то не понимаю, это же дикие тормоза на 32 битнике. Но люди то солидные писали, в чем прикол? Собственно это вариант общий для разных процев, обрамлен ifndef ARCH_MEMCPY, но. для Арм версия такая for (i = __n >> 3; i > 0; i--) { 15 *d++ = *s++; 16 *d++ = *s++; 17 *d++ = *s++; 18 *d++ = *s++; 19 *d++ = *s++; 20 *d++ = *s++; 21 *d++ = *s++; 22 *d++ = *s++; 23 } Что не шибко лучше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kolobok0 0 21 ноября, 2013 Опубликовано 21 ноября, 2013 · Жалоба ...Что не шибко лучше. вроде как у мелкомягких было сразу по регистру перекидовали. перед циклом - деление на размер, после - добивание побайтно. в проекте с армами пока не дошёл, до копирования памяти (только вот начал упаковку изернет стэка). обращу внимание, спасибо! и... глупый вопрос: а точно оптимизация была включена при компиляции? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DASM 0 21 ноября, 2013 Опубликовано 21 ноября, 2013 · Жалоба Так это же исходники линуксовые, с kernel.org .Мне собственно говоря copy_to_user нужен, но он в итоге зовет этот самый memcpy. Объемы копирования большие, вот и заинтересовался скоростью.. Это же четыре обращения к памяти, в случае 32 битной и вне кеша — это даже не в четыре раза потеря, поболее может быть вроде как. char * никакой оптимизатор имхо заменять права не имеет на int* Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mantech 53 21 ноября, 2013 Опубликовано 21 ноября, 2013 · Жалоба в случае 32 битной и вне кеша — это даже не в четыре раза потеря, поболее может быть вроде как. char * Дык наверно так делают, чтобы получить любое кол-во копируемых байт, а не кратно 4м. Например, как такой операцией скопировать 5 или 6 байт? 32х бытовое копирование запросит как минимум 8, а если память выделена только под 5? Если уж так важна скорость, и объемы копирования не 10 байт, а значительно больше - используйте DMA в 32х битном режиме... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
winipuh 0 21 ноября, 2013 Опубликовано 21 ноября, 2013 (изменено) · Жалоба Дык наверно так делают, чтобы получить любое кол-во копируемых байт, а не кратно 4м. Например, как такой операцией скопировать 5 или 6 байт? 32х бытовое копирование запросит как минимум 8, а если память выделена только под 5? Если уж так важна скорость, и объемы копирования не 10 байт, а значительно больше - используйте DMA в 32х битном режиме... Да Вы чего? Гляньте исходники newlib, bionic... Оптимизированная версия memcpy проверяет выравнивание src и dst и выбирает вариант - копирование LDM/STM блоками по 4 слова, копирование в loop-е по словам, по полусловам, по байтам. У Cortex-A помимо этого еще есть плюшки с Neon-ом... Полагаю, что ТС прекрасно знает это и без нас. И вопрос его, надо полагать, заключается в том, что "WTF? Зачем тупо выбирать самый пессимистичный вариант?" (с учетом того, что эта версия memcpy откуда-то там из линуксового ядра, стало быть писал ее не дурак)... Хотя, надо отметить, что в том же newlib-е подобный вариант тоже присутствует: #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) while (len0--) { *dst++ = *src++; } Изменено 21 ноября, 2013 пользователем winipuh Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 21 ноября, 2013 Опубликовано 21 ноября, 2013 · Жалоба Вот, уже была тема, где memcpy'ями мерились:) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sasamy 0 22 ноября, 2013 Опубликовано 22 ноября, 2013 (изменено) · Жалоба Так это же исходники линуксовые, с kernel.org .Мне собственно говоря copy_to_user нужен, но он в итоге зовет этот самый memcpy. Обсуждения оптимизаций для ARM были http://comments.gmane.org/gmane.linux.port...m.kernel/251708 чем закончилось не знаю - посмотрите исходники текущего ядра с kernel.org, возможно уже все не так пессимистично как вы думаете :) По крайней мере в новостях что-то припоминаю - проскакивало про использование NEON в ядре. Изменено 22 ноября, 2013 пользователем sasamy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Harbour 0 22 ноября, 2013 Опубликовано 22 ноября, 2013 · Жалоба в Linux все просто - народ верит только бенчмаркам, тема с memcpy всплывает в рассылке по паре раз в год, но arch-маинтейнеры не лыком шиты - и тормозной код никак не пройдет. код memcpy отличается для каждой архитектуры так как особенность конвейеров, кешей, стандартных задержек между кешем и памятью, видов и исполнения инструкций (выборка/декодирование/исполнение) у каждой one разный. более того - следует учитывать ньюансы переключения задач, сбросов кешей при этом и сохранения регистров сопроцессоров - например, код memcpy, который жестоко юзает FPU/SIMD инструкции фиг пройдет, так как при переключении задач закукуаешься их всех сохранять ;) В данном случае мы видим классический loop unroll сделанный вручную под конвейер ARM, без каких либо надежд на gcc ;) Если есть сомнения - пишем свою версию и тестим на железе - при дальнейших раскопках лагов, все станет понятно P.S. педивикия - unroll Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
griabig 0 22 ноября, 2013 Опубликовано 22 ноября, 2013 · Жалоба 598 */ 599 void *memcpy(void *dest, const void *src, size_t count) 600 { 601 char *tmp = dest; 602 const char *s = src; 603 604 while (count--) 605 *tmp++ = *s++; 606 return dest; 607 } 608 EXPORT_SYMBOL(memcpy); Такой вот сурец из string.c ... видел более оптимизированную версию с раскруткой цикла. Что то не понимаю, это же дикие тормоза на 32 битнике. Но люди то солидные писали, в чем прикол? Собственно это вариант общий для разных процев, обрамлен ifndef ARCH_MEMCPY, но. для Арм версия такая for (i = __n >> 3; i > 0; i--) { 15 *d++ = *s++; 16 *d++ = *s++; 17 *d++ = *s++; 18 *d++ = *s++; 19 *d++ = *s++; 20 *d++ = *s++; 21 *d++ = *s++; 22 *d++ = *s++; 23 } Что не шибко лучше. Если я правильно понял, то приведенный код для ARM взят из arch/arm/boot/compressed/string.c. Если я не ошибаюсь, то данный код используется исключительно при загрузке ядра. А "боевая" версия memcpy находится уже в arch/arm/lib/memcpy.S и arch/arm/lib/template.S и реализована полностью на ассемблере. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DASM 0 22 ноября, 2013 Опубликовано 22 ноября, 2013 · Жалоба Да, верно, это именно и происходит в реальности, спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться