Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.144.227.231] |
|
Сообщ.
#1
,
|
|
|
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() на гиговом Атлоне, но может можно его ещё ускорить ? Спасибо |
Сообщ.
#2
,
|
|
|
Здесь нужно исходить из того, что...
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'. |
Сообщ.
#3
,
|
|
|
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 походу, ничего быстрее не придумать... |
Сообщ.
#4
,
|
|
|
Почитай ещё доки об инструкциях 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'. |
Сообщ.
#5
,
|
|
|
самый быстрый вариант
[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; } |
Сообщ.
#6
,
|
|
|
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 |
Сообщ.
#7
,
|
|
|
Оригинально... Мог бы тогда уж все 8 регистров задействовать
Раз уж всё-таки используешь prefetch0 (может, это глюк, но в моих доках без буквы 't', но это не важно), который для P-III и Athlon'ов, почитай всё-таки MOVAPS и MOVUPS и поищи аналоги для Athlon |
Сообщ.
#8
,
|
|
|
не надо сарказма
4 регистра используются по той простой причине, что только так происходит прирост в скорости, не большо (10-15\%) но есть... А это всё, что можно сделать для атлона, не ХР - SSE MMX и всё... скомпили тот файлик, на который я положил ссылку и посмотри сам на результаты - яот туды уже выкинул memcpy() и прочую фигню, но поймёшь в чём дело |
Сообщ.
#9
,
|
|
|
в твоих доках глюки - prefetchtx, x=0,1,2,nt
|
Сообщ.
#10
,
|
|
|
Да. и ещё одно
если цикл короткий. типа 3-4 итерации. то лучше это дело записать сплошняком - работает быстрее, учитывая архитектуру процов... по этому у меня 4 movq а посредине prefetcht0 - чтение 32 байт, прекэширование слудующих, запись... когда запись заканчивается, данные уже в кеше. а если сделать movq mm0, [] prefetcht0 [esi] movntq [edi], mm0 то так только хуже будет, с всязи с тем, что данные будут прекешировать без надобности по 3 раза Всего хорошего VuDZ |
Сообщ.
#11
,
|
|
|
Я б с удовольствием (скомпилировал), но у меня VC нету как такового и комп у меня P-II
Кстати, я посмотрел - есть и prefetch, и prefetchT, и даже prefetchW оказывается Слушай, может, ты знаешь, где можно достать доки по всем инструкциям (желательно до P-4 и с описанием ??? И доки типа TechHelp и Ralf Brown's..., но поновее и покруче, а то TechHelp'а новее шестого я что-то никак не найду Короче, всё в этом духе... да (как в анекдоте) побольше-побольше... )) |
Сообщ.
#12
,
|
|
|
1. Процессоры PentiumIII, Athlon и другие...
2. Я заказывал в саппорте AMD и техническую документацию на СД. Скоро должна прийти А так - берёш яндекс или что-то в этом роде, и начинаешь искать |