Зацените мой UltraFastStrCopy32

Тема в разделе "WASM.WIN32", создана пользователем Colombo, 17 янв 2007.

  1. Colombo

    Colombo New Member

    Публикаций:
    0
    Регистрация:
    15 авг 2005
    Сообщения:
    20
    Единственный минус нужно окно в +8 байт, юзаю MMX.
    Код (Text):
    1. DEST <- eax
    2. SRC <- edx
    3.  
    4.         PUSH    EDI
    5.         PUSH    ESI
    6.         MOV     ESI,EAX
    7.         MOV     EDI,EDX
    8.         MOV     ECX,0FFFFFFFFH  
    9.         XOR     AL,AL
    10.         REPNE   SCASB
    11.         NOT     ECX
    12.         SHR     ECX,3
    13.         @Loop:
    14.         DD $CA3C6F0F  //movq mm7, [edx+ecx*8]
    15.         DD $CE3C7F0F  //movq [esi+ecx*8], mm7
    16.         dec ecx
    17.         jnl @loop
    18.         DW $770F    //emms MMX.Flags = FFFF
    19.         POP     ESI
    20.         POP     EDI
    Тесты показывают ускорение на 24% аналога виндовса lstrcpy.
    Кстати дефолтовый strcopy от делфи, быстрее lstrcpy на 8%.
    Можно еще как то ускорить юзая инструкции от новых технологий?
     
  2. MikDay

    MikDay New Member

    Публикаций:
    0
    Регистрация:
    5 май 2005
    Сообщения:
    32
    Адрес:
    Minsk
    Командой
    SHR ECX,3
    можно потерять до 7 байт в хвосте строки.
    Если добавить INC ECX, то потери не будет, но нужно увеличить максимальный размер примающей строки на 8 байт.
    Это увеличение (INC ECX) допустимо только в том случае, если за копируемой строкой "твоя память", иначе можно нарушить границу.
     
  3. Colombo

    Colombo New Member

    Публикаций:
    0
    Регистрация:
    15 авг 2005
    Сообщения:
    20
    мм не ) потерь нету, тут всегда выходит копирует от 1 до 8 байт больше, потому что сначала скопирует а потом проверит счетчик на 0 :derisive:
     
  4. explosion

    explosion Member

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    34
    можно. Используй SIMD инструкции (SSE,SSE2,SSE3), они позволяют копировать по 16 байт за один такт проца.
    Там по моему еще есть быстрые команды параллельного умножения (4 числа по 4 байта за один такт), вычисление синусов, квадратных корней.

    Если не секрет,как ты измерил тем более с такой точностью? Не следует забывать, что система windows не является ос реального времени, у нее также есть понятие как виртуальная память. Если ты копируешь большой объем оперативной памяти, есть большой шанс что часть диспетчер будет подгружать с диска. Где-то больше, а где-то нет. Я думаю разброс в 5-10% по скорости - не показатель...

    используй fasm, не мучийся. Он понимает такие вещи

    выходит, у тебя длина строки (или размер буфера) должна быть всегда кратна 8?:) а если нет, то рискуем схватить general protection fault при чтении или подтереть чужие байты при записи
     
  5. Colombo

    Colombo New Member

    Публикаций:
    0
    Регистрация:
    15 авг 2005
    Сообщения:
    20
    замерил время 10 млн копирований в стэк одной и той же строки тремя разными функциями, отличия явные!
    В винде стока всего не оптимизировано! MMX вышел еще с P200, еще 98-ая винда при установке могла бы определять наличие MMX и ставить заточенные под него системные библиотеки, прирост скорости был бы ощутим, всеголиш при дополнительных 8 байт затратах на HeapAlloc.
     
  6. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Colombo
    На старых камнях получите #UD.

    Это можно сделать гораздо оптимальнее без использования строчных инструкций.

    Так быстрее:
    Код (Text):
    1. DD $CA3C6F0F  //movq mm7, [edx+ecx*8]
    2. sub ecx,1
    3. DD $CE3C7F0F  //movq [esi+ecx*8], mm7
    4. jnl @loop
    + выравнивание метки цикла.
     
  7. Dr.Golova

    Dr.Golova New Member

    Публикаций:
    0
    Регистрация:
    7 сен 2002
    Сообщения:
    348
    > могла бы определять наличие MMX и ставить заточенные под него системные библиотеки

    Срать в MMX/SSE регистры? Предположим, они все заполнены моими пользовательскими данными. Что дальше?
    Мне их сохранять перед каждым вызовом АПИ, или это виндовые функции должны делать? Учитывая что обычно строчки не более нескольких десятков байт, явная просадка по производительности обеспечена. Уверяю, что если мне понадобится оптимизированная функция для копирования мегабайтов из back-buffer'а в видеопамять, она будет востребована максимум в паре месть мегабайтной программы.
     
  8. explosion

    explosion Member

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    34
    А между прочим, дизассемблирование стандартных библиотечных функций memset и memcpy мне показало, что в них есть поддержка SSE2. Но используется она только при наличии этого самого SSE2 и если блок выровнен в памяти. И перед использованием регистры SSE сохраняются. В противном случае используются обычные movs и stos

    получается идея далеко не нова...

    а ты попробуй сравни свою функцию с memcpy (при учете высшеперечисленных факторов для использования SSE2)

    и потом Dr.Golova верно подметил, твоя функция испортила и не восстановила mmx регистры (а т.к. они используют внутреннюю память сопроцессора, то и регистры сопроцессора). А возможно кто то их использовал
     
  9. Colombo

    Colombo New Member

    Публикаций:
    0
    Регистрация:
    15 авг 2005
    Сообщения:
    20
    сколько дизасемблирую проги, не видел чтобы до вызова пользовательской функции fpu и mmx регистры не сливались в свои qword ptr места. Ведь данные копируются в регистры только когда их нужно обработать, а хранятся они всегда в своих 8 байтовых ячейках.

    тут максимум это надо сбрасывать флаги. Если их не сбросить, то при первом ProcessMessages прога падает.
     
  10. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    "дизассемблирование стандартных библиотечных функций memset и memcpy мне показало"

    Странно, если я компилирую код в Release Build - таких функций нет - они все заменены на inline (STOS and MOVS).
     
  11. explosion

    explosion Member

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    34
    VisualStudio2005 c++

    поставь memset
    понажимай f11 при отладке и увидишь:)

    на инлайн заменяет потому что у тебя опция компилятора стоит