Единственный минус нужно окно в +8 байт, юзаю MMX. Код (Text): DEST <- eax SRC <- edx PUSH EDI PUSH ESI MOV ESI,EAX MOV EDI,EDX MOV ECX,0FFFFFFFFH XOR AL,AL REPNE SCASB NOT ECX SHR ECX,3 @Loop: DD $CA3C6F0F //movq mm7, [edx+ecx*8] DD $CE3C7F0F //movq [esi+ecx*8], mm7 dec ecx jnl @loop DW $770F //emms MMX.Flags = FFFF POP ESI POP EDI Тесты показывают ускорение на 24% аналога виндовса lstrcpy. Кстати дефолтовый strcopy от делфи, быстрее lstrcpy на 8%. Можно еще как то ускорить юзая инструкции от новых технологий?
Командой SHR ECX,3 можно потерять до 7 байт в хвосте строки. Если добавить INC ECX, то потери не будет, но нужно увеличить максимальный размер примающей строки на 8 байт. Это увеличение (INC ECX) допустимо только в том случае, если за копируемой строкой "твоя память", иначе можно нарушить границу.
мм не ) потерь нету, тут всегда выходит копирует от 1 до 8 байт больше, потому что сначала скопирует а потом проверит счетчик на 0
можно. Используй SIMD инструкции (SSE,SSE2,SSE3), они позволяют копировать по 16 байт за один такт проца. Там по моему еще есть быстрые команды параллельного умножения (4 числа по 4 байта за один такт), вычисление синусов, квадратных корней. Если не секрет,как ты измерил тем более с такой точностью? Не следует забывать, что система windows не является ос реального времени, у нее также есть понятие как виртуальная память. Если ты копируешь большой объем оперативной памяти, есть большой шанс что часть диспетчер будет подгружать с диска. Где-то больше, а где-то нет. Я думаю разброс в 5-10% по скорости - не показатель... используй fasm, не мучийся. Он понимает такие вещи выходит, у тебя длина строки (или размер буфера) должна быть всегда кратна 8? а если нет, то рискуем схватить general protection fault при чтении или подтереть чужие байты при записи
замерил время 10 млн копирований в стэк одной и той же строки тремя разными функциями, отличия явные! В винде стока всего не оптимизировано! MMX вышел еще с P200, еще 98-ая винда при установке могла бы определять наличие MMX и ставить заточенные под него системные библиотеки, прирост скорости был бы ощутим, всеголиш при дополнительных 8 байт затратах на HeapAlloc.
Colombo На старых камнях получите #UD. Это можно сделать гораздо оптимальнее без использования строчных инструкций. Так быстрее: Код (Text): DD $CA3C6F0F //movq mm7, [edx+ecx*8] sub ecx,1 DD $CE3C7F0F //movq [esi+ecx*8], mm7 jnl @loop + выравнивание метки цикла.
> могла бы определять наличие MMX и ставить заточенные под него системные библиотеки Срать в MMX/SSE регистры? Предположим, они все заполнены моими пользовательскими данными. Что дальше? Мне их сохранять перед каждым вызовом АПИ, или это виндовые функции должны делать? Учитывая что обычно строчки не более нескольких десятков байт, явная просадка по производительности обеспечена. Уверяю, что если мне понадобится оптимизированная функция для копирования мегабайтов из back-buffer'а в видеопамять, она будет востребована максимум в паре месть мегабайтной программы.
А между прочим, дизассемблирование стандартных библиотечных функций memset и memcpy мне показало, что в них есть поддержка SSE2. Но используется она только при наличии этого самого SSE2 и если блок выровнен в памяти. И перед использованием регистры SSE сохраняются. В противном случае используются обычные movs и stos получается идея далеко не нова... а ты попробуй сравни свою функцию с memcpy (при учете высшеперечисленных факторов для использования SSE2) и потом Dr.Golova верно подметил, твоя функция испортила и не восстановила mmx регистры (а т.к. они используют внутреннюю память сопроцессора, то и регистры сопроцессора). А возможно кто то их использовал
сколько дизасемблирую проги, не видел чтобы до вызова пользовательской функции fpu и mmx регистры не сливались в свои qword ptr места. Ведь данные копируются в регистры только когда их нужно обработать, а хранятся они всегда в своих 8 байтовых ячейках. тут максимум это надо сбрасывать флаги. Если их не сбросить, то при первом ProcessMessages прога падает.
"дизассемблирование стандартных библиотечных функций memset и memcpy мне показало" Странно, если я компилирую код в Release Build - таких функций нет - они все заменены на inline (STOS and MOVS).
VisualStudio2005 c++ поставь memset понажимай f11 при отладке и увидишь на инлайн заменяет потому что у тебя опция компилятора стоит