WWW.ИСХОДНИКИ.РУ cpp.sources.ru
java.sources.ru web.sources.ru soft.sources.ru
jdbc.sources.ru asp.sources.ru api.sources.ru

  Форум на исходниках
  ASM
  Копирование памяти

СПРОСИТЬ  ОТВЕТИТЬ
профайл | регистрация | faq

Автор Тема:   Копирование памяти
VuDZ опубликован 22-12-2001 11:56 MSK   Click Here to See the Profile for VuDZ  
Subj такой - надо с максимально озможной скоростью копировать данные из одного куска памяти в другой. Подошёл бы и memcpy(), но он очень медленный. Этот вопрос скорее по асму, но может кто ответит. Вот что есть сейчас:

_asm
{
mov esi, p2;
mov edi, p3;
mov ecx, copy;
shr ecx, 3;
sub ecx, 1; // for first step
l_p3: movq mm0, [esi + ecx*4];
movq [edi+ecx*4], mm0;
dec ecx;
jnz l_p3;
}
_asm emms;
Дапоможите, хто чем может (желательно не теорией)
ЗЫ prefetcht уже использовался - с ним только хуже
mm0 + mm1 + mm2 + mm3 одновременно то же использовал.
сейчвс этот код на 36% быстрее. чем memcpy() на гиговом Атлоне, но может можно его ещё ускорить ?
Спасибо

7in опубликован 22-12-2001 22:42 MSK     Click Here to See the Profile for 7in  Click Here to Email 7in     
Здесь нужно исходить из того, что...
1. Читать/записывать память лучше всего по адресу, кратному 8 (для 64-битовой шины). А т.к. возможны разные комбинации адресов, в т.ч. когда первый адрес (исходный) кратен 8, а второй (куда записываем) - нет, возникает больше трудностей, поэтому я предлагаю выравнивать хотябы один адрес (наверное, если медленнее чтение, то первый, если запись, то второй). Но это ИМХО бессмысленно, если копируются небольшие участки памяти (несколько байт).
2. Копировать лучше по 8 байт (а у тебя тут явная ошибка - не [...ecx*4], а [...ecx*8-8]). А 'sub ecx,1' здесь вообще не нужен.
3. Размер блока может быть не кратен 8, так что твой вариант надо доработать!

Могу сам написать процедуру вместе с выравниванием, только ты мне напиши:
1. Что быстрее - чтение или запись?
2. Манипуляции с MMX действительно быстрее, чем 'rep movsd'? MMX производит впечатление, что должен работать быстрее, но из-за jnz (а на это наверняка и уходит основное время) на самом деле может оказаться медленнее.
3. Кстати, не ленись, попробуй копировать через FPU (загружать в ST(0) по 8 байт и записывать оттуда :)

Только при тестировании проследи, чтобы адреса исходных блоков ВСЕГДА были кратны 8 (а лучше 16 :). И сделай второй тест, когда адреса на 1 больше кратного 8 значения. И не забудь, что при 'movq' делается 'shr ecx,3', а при 'rep movsd' - 'shr ecx,2'.

VuDZ опубликован 23-12-2001 06:45 MSK     Click Here to See the Profile for VuDZ    
1. Выравнивание везде 16 байт - это даёт ещё некий прирост в скорости
2. movq mm0, [esi + ecx*4]; - movq и копирут 64бита сразу, а та да, ошибся, ecx*8 - но разница минимальна - эти данные уже лежали в кэше
3. размер блока _всегда_ кратен 8, точнее 16
....
копирование 1Mb for 50 times
MMX - 171-181 ms
rep movsd - 260 ms
memcpy() - 250 ms
походу, ничего быстрее не придумать...
7in опубликован 23-12-2001 22:58 MSK     Click Here to See the Profile for 7in  Click Here to Email 7in     
Почитай ещё доки об инструкциях MOVAPS/MOVUPS (для Pentium-III :) . Они записывают сразу 16 байт! Правда, [...ecx*16] уже не получится, но это вопрос номер 2...
Только это уже не 'IA MMX', а 'IA MMX-2'

На Athlon'е может не работать, но Athlon вроде тоже 128-битный (или я глючу?). Значит и для него что-то подобное есть... :)

Удачи!!!

---------------------------------------------
P.S. Кстати, попробовал я копирование через FPU (fild/fistp) на Pentium-II... Работает примерно так же, как и 'rep movsd'.

VuDZ опубликован 24-12-2001 06:42 MSK     Click Here to See the Profile for VuDZ    
самый быстрый вариант
[code]
{
mov esi, p6;
mov edi, p1;
mov ecx, copy;
shr ecx, 3; // devide on 8
l_p3: movq mm0, [esi + ecx * 8-8]; // loading to cashe first32 bytes
movq mm1, [esi + ecx * 8 - 16];
movq mm2, [esi + ecx * 8 - 24];
movq mm3, [esi + ecx * 8 - 32];
// prefetcht0 [esi + ecx * 8 - 33]; // preload next 32 bytes
movntq [edi + ecx * 8], mm0;
movntq [edi + ecx * 8 - 8], mm1;
movntq [edi + ecx * 8 - 16], mm2;
movntq [edi + ecx * 8 - 32], mm3;
sub ecx, 4;
jnz l_p3;
}
VuDZ опубликован 24-12-2001 06:51 MSK     Click Here to See the Profile for VuDZ    
Ops....
что то меня проглючило
_asm
{
mov esi, p6;
mov ecx, copy;
prefetcht0 [esi + ecx - 32]; // preload next 32 bytes
mov edi, p1;
shr ecx, 3; // devide on 8
l_p3: movq mm0, [esi + ecx * 8 - 8]; // loading to cashe first32 bytes
movq mm1, [esi + ecx * 8 - 16];
movq mm2, [esi + ecx * 8 - 24];
movq mm3, [esi + ecx * 8 - 32];
prefetcht0 [esi + ecx * 8 - 64]; // preload next 32 bytes
movntq [edi + ecx * 8 - 8], mm0;
movntq [edi + ecx * 8 - 16], mm1;
movntq [edi + ecx * 8 - 24], mm2;
movntq [edi + ecx * 8 - 32], mm3;
sub ecx, 4;
jnz l_p3;
}
_asm emms;

http://vudz.by.ru/misc/asm_copy.htm

7in опубликован 24-12-2001 23:51 MSK     Click Here to See the Profile for 7in  Click Here to Email 7in     
Оригинально... Мог бы тогда уж все 8 регистров задействовать :)
Раз уж всё-таки используешь prefetch0 (может, это глюк, но в моих доках без буквы 't', но это не важно), который для P-III и Athlon'ов, почитай всё-таки MOVAPS и MOVUPS и поищи аналоги для Athlon ;)
VuDZ опубликован 25-12-2001 00:16 MSK     Click Here to See the Profile for VuDZ    
не надо сарказма
4 регистра используются по той простой причине, что только так происходит прирост в скорости, не большо (10-15%) но есть...
А это всё, что можно сделать для атлона, не ХР - SSE MMX и всё...
скомпили тот файлик, на который я положил ссылку и посмотри сам на результаты - яот туды уже выкинул memcpy() и прочую фигню, но поймёшь в чём дело
VuDZ опубликован 25-12-2001 00:16 MSK     Click Here to See the Profile for VuDZ    
в твоих доках глюки - prefetchtx, x=0,1,2,nt
VuDZ опубликован 25-12-2001 09:11 MSK     Click Here to See the Profile for VuDZ    
Да. и ещё одно
если цикл короткий. типа 3-4 итерации. то лучше это дело записать сплошняком - работает быстрее, учитывая архитектуру процов...
по этому у меня 4 movq а посредине prefetcht0 - чтение 32 байт, прекэширование слудующих, запись...
когда запись заканчивается, данные уже в кеше.
а если сделать
movq mm0, []
prefetcht0 [esi]
movntq [edi], mm0

то так только хуже будет, с всязи с тем, что данные будут прекешировать без надобности по 3 раза
Всего хорошего
VuDZ

7in опубликован 25-12-2001 21:09 MSK     Click Here to See the Profile for 7in  Click Here to Email 7in     
Я б с удовольствием (скомпилировал), но у меня VC нету как такового и комп у меня P-II :(

Кстати, я посмотрел - есть и prefetch, и prefetchT, и даже prefetchW оказывается :)

Слушай, может, ты знаешь, где можно достать доки по всем инструкциям (желательно до P-4 и с описанием :) ???
И доки типа TechHelp и Ralf Brown's..., но поновее и покруче, а то TechHelp'а новее шестого я что-то никак не найду :)
Короче, всё в этом духе... да (как в анекдоте) побольше-побольше... :)))

VuDZ опубликован 26-12-2001 06:16 MSK     Click Here to See the Profile for VuDZ    
1. Процессоры PentiumIII, Athlon и другие...
2. Я заказывал в саппорте AMD и техническую документацию на СД. Скоро должна прийти
А так - берёш яндекс или что-то в этом роде, и начинаешь искать

СПРОСИТЬ  ОТВЕТИТЬ
Перейти:


E-mail | WWW.ИСХОДНИКИ.RU

Powered by: Ultimate Bulletin Board, Freeware Version 5.10a
Purchase our Licensed Version- which adds many more features!
© Infopop Corporation (formerly Madrona Park, Inc.), 1998 - 2000.