|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Сен 4, 2003 19:49:31 Edmond Быстрее чем.. У меня получилось быстрее на 0.14 секунды. Проверил 3 раза. lodsb выполняется медленнее чем mov al,[esi]. Во всяком случае так говорит Зубков в соей книге... Edmond А где приват, если не секрет?... |
|
|
Дата: Сен 4, 2003 19:58:00 KiNDeR А где приват, если не секрет?... Какой??? |
|
|
Дата: Сен 4, 2003 20:01:36 KiNDeR Проглядел mov!!! mov al,byte ptr [esi] |
|
|
Дата: Сен 4, 2003 20:06:05 Edmond Про приват... Это я неправильно прочитал...сори... |
|
|
Дата: Сен 8, 2003 18:54:37 · Поправил: Black_mirror Edmond @@: ; ------- Цикл ------------ lodsb sub al,30h jb short endproc ;; Если меньше -- конец cmp al,9 ja short endproc lea edx,[edx+edx*4] lea edx,[eax+edx*2] ;; Если сумматор превысит это значение, ;; значит преобразование старшей части завершено Str_to_Int64_next:: cmp edx,19999999h ;; ffffffffh/ah = 19999999h jna @B а что будет этому циклу дать строку 4294967296? ;; Теперь edx:eax - содержат 64-bits текущее число. mov ecx,eax ;; Прибавляем последний разряд xor eax,eax lodsb sub al,30h jb short @F ;; Если меньше -- конец cmp al,9 ja short @F ;; старшая часть числа * 10 ;; младшая * 10 push eax mov eax,ecx mov ecx,edx shl ecx,1 mul CONSTANT_10 lea ecx,[ecx+ecx*4] add edx,ecx pop ecx ;; edx:eax = edx:eax + ecx (ecx = последний символ - 30h) add eax,ecx adc edx,0 А если младшая часть числа > 19999999h? |
|
|
Дата: Сен 8, 2003 18:57:51 Вопросы относятся к коду который находится выше. Защита от спама - страшная штука! |
|
|
Дата: Сен 8, 2003 19:42:54 Black_mirror а что будет этому циклу дать строку 4294967296? Всё ОК. Сам посмотри. ;; ffffffffh/ah = 19999999h cmp edx,19999999h jna @B Или я что-то пропустил? |
|
|
Дата: Сен 8, 2003 23:33:49 Edmond edx=19999999h eax=6,7,8,9 lea edx,[edx+edx*4] edx=7ffffffdh lea edx,[eax+edx*2] edx=0,1,2,3 а во втором куске кода, при умножении ecx на 10 теряется старшая часть произведения. |
|
|
Дата: Сен 9, 2003 18:02:37 Black_mirror Гм....м..м.... Я вроде всё проверял.. Ай яй, яй, яяй..!!!!! Как же я это мог пропустить??? Нет ну сам же помню, сидел всё высчитал на калькуляторе. Нет ну помню же, что предусмотрел.. Мдя. Black_mirror Большое спасибо!!!! Хорошо поймал ошибку.. |
|
|
Дата: Сен 9, 2003 19:29:31 Щас доделываю оптимизацию этого дела под... SSE2 :)))) |
|
|
Дата: Сен 9, 2003 20:32:18 boozook Вовооо... Действитель но будет ULIB -- UltraLib |
|
|
Дата: Сен 10, 2003 01:06:24 · Поправил: boozook Нихрена не понять, в каком порядке он выполняет каманды? С конца что-ли? Ожидал большего... но так тоже быстрее, где-то в 1.5-3 раза (судя по тому что выдает rdtsc) ;Вход: ; edi - указатель на строку ;Выход: ; если ошибок нет, CF=0, результат в eax, ; edi - указывает на завершающий символ; ; CF=1, если ошибка
.const
ALIGN 16
h3030_3030 QWORD 3030303030303030h,3030303030303030h
h0909_0909 QWORD 0909090909090909h,0909090909090909h
; 1 2 3 4 5 6 7 8
step1 WORD 1000,100, 1000,100, 1000,100, 10,1
step2 WORD 10000, 100, 1, 1, 4 dup (?)
boost WORD 10,1, 1,0
.code
Str2Int32_SSE2 proc ; example: [edi]="123456t"
movupd xmm0,[edi] ; ... xx 00 36 35 34 33 32 31
mov edx,64
mov eax,[edi]
sub al,30h
cmp byte ptr h0909_0909,al ; пустая строка - CF<-1 и выход
jc exit
pxor xmm3,xmm3
sub ah,30h
cmp ah,9
ja only_one ;всего 1 цифра - SSE ни к чему
psubb xmm0,h3030_3030 ; ... xx D0 06 05 04 03 02 01
shr eax,16
sub al,30h
cmp al,9
ja only_two ; длина строки - 2цифры
movapd xmm1,xmm0
pcmpgtb xmm1,h0909_0909 ; FFh - если в пределах от 10 до 127, иначе 00h
por xmm1,xmm0 ; если знаковый бит установлен, значит это терминальный символ
sub ah,30h
cmp ah,9
ja only_three ; длина строки - 3цифры
pmovmskb eax,xmm1 ; eax = x1000000b
bsf eax,eax ; длина строки в eax
je error ; более 16 символов
add edi,eax
shl eax,3
sub edx,eax ; edx = 8*(8-длина строки) = 16
js more8 ; более 8 символов
je no_shift
movd xmm1,edx
psllq xmm0,xmm1 ; ................ 06 05 04 03 02 01 00 00
no_shift:
punpcklbw xmm0,xmm3 ; 0006 0005 0004 0003 0002 0001 0000 0000
pmaddwd xmm0,step1 ; 0006+0050 0400+3000 0200+1000 0000+0000
packssdw xmm0,xmm3 ; ................... 0056 3400 1200 0000
pmaddwd xmm0,step2 ; ................... 0056+3400 120000+0
movapd xmm1,xmm0
psrlq xmm0,4*8 ; .............................. 3456
paddd xmm0,xmm1 ; .............................. 123456
movd eax,xmm0
ret
only_one:
and eax,15
inc edi
ret
only_two:
punpcklbw xmm0,xmm3
pmaddwd xmm0,boost
movd eax,xmm0
add edi,2
ret
only_three:
punpcklbw xmm0,xmm3
pmaddwd xmm0,boost
packssdw xmm0,xmm3
pmaddwd xmm0,boost
movd eax,xmm0
add edi,3
ret
more8:
pextrw edx,xmm0,4
punpcklbw xmm0,xmm3
pmaddwd xmm0,step1
packssdw xmm0,xmm7
pmaddwd xmm0,step2
movapd xmm1,xmm0
psrlq xmm0,4*8
paddd xmm0,xmm1
cmp eax,72
je nine ; девять знаков
;ten
mov al,dl
shr edx,8
lea eax,[eax+eax*4]
lea edx,[edx+eax*2]
movd eax,xmm0
lea eax,[eax+eax*4]
lea eax,[eax+eax*4]
shl eax,2
jc exit
add eax,edx
ret
nine:
and edx,00001111b
movd eax,xmm0
lea eax,[eax+eax*4]
lea eax,[edx+eax*2]
ret
error:
stc ; ошибка - установить флаг CF
exit:
ret
Str2Int32_SSE2 endp
Думаю, это можно еще оптимизироать... Большая часть времени уходит на всякие проверки и подсчет длины строки |
|
|
Дата: Сен 10, 2003 01:53:56 Например, можно попробовать сделать подсчет длины строки параллельно перемножениям, а потом, в конце, все поделить на 10 в нужной степени..... |
|
|
Дата: Сен 10, 2003 04:21:56c3ah dd 3a3a3a3ah,3a3a3a3ah,3a3a3a3ah,3a3a3a3ah c10 dd 0a0a0a0ah,0a0a0a0ah,0a0a0a0ah,0a0a0a0ah c100 dd 100,100,100,100 c10000 dw 10000,10000,10000,10000,10000,10000,10000,10000,10000 c00ff dd 0ff00ffh,0ff00ffh,0ff00ffh,0ff00ffh str16toint64: ;вход: ecx - строка, не более 16 цифр ;выход: edx:eax - число, ecx - количество преобразованных символов push ebp mov ebp,esp pxor xmm0,xmm0 sub esp,32 and esp,-16 movdqu [esp],xmm0 movdqu xmm0,[ecx] ;загружает 16 символов ;в младшем байте-старшая цифра psubb xmm0,dqword [c3ah];вычитаем из них '0'+10 pmovmskb eax,xmm0 ;в eax-знаковые биты, если бит=0 - не цифра movdqa xmm3,dqword [c10] paddb xmm0,xmm3 ;добавляем 10 pmovmskb ecx,xmm0 ;если бит=1 - не цифра not eax ;теперь в eax также movdqu [esp+16],xmm0 ;сохраняем число в стеке, or eax,ecx ;если бит=1 - не цифра bsf ecx,eax ;находим первую не цифру ;в ecx - количество цифр в числе movdqu xmm0,[esp+ecx] ;загружаем число так, ;чтобы младшая цифра попала в старший байт movdqu xmm1,xmm0 ;и будем считать ее номер нечетным pmullw xmm0,xmm3 ;умножаем нечетные цифры на 10 psrlw xmm1,8 ;прибавляем к ним четные paddb xmm0,xmm1 ;w[i]=b[2i+1]+b[2i]*10 pand xmm0,dqword [c00ff];в старшем байте был мусор movdqu xmm1,xmm0 pmullw xmm0,dqword [c100];умножаем четные группы из 2х цифр на 100 psrld xmm1,16 ;и прибавляем к ним нечетные paddw xmm0,xmm1 ;d3=w7+w6*100,d2=w5+w4*100,d1=w3+w2*100,d0=w0+w1*100 movdqu xmm1,xmm0 pshufd xmm2,xmm0,10110001b pslld xmm1,16 movdqa xmm3,dqword [c10000] pmullw xmm0,xmm3 pmulhw xmm1,xmm3 por xmm0,xmm1 paddd xmm0,xmm2 ;d2=d2*10000+d3,d0=d0*10000+d1 movdqu [esp],xmm0 mov eax,100000000 ;edx:eax=d0*100000000+d2 mul dword [esp] add eax,[esp+4] adc edx,0 mov esp,ebp pop ebp ret to boozook К сожалению мой процессор SSE2 не знает, поэтому протестировать не смог. Скорее всего здесь скрываются баги. Максимальное число, которое переводит эта функция: 9,999,999,999,999,999. Просьба отладить, и замерить производительность 8) |
|
|
Дата: Сен 10, 2003 14:58:23 · Поправил: boozook работает... cкажем так, результаты не очень :) небольшие баги: - перед данными нужен ALIGN 16, а вот movdqu будет работать без выравнивания [esp] - в c10000 лишнее слово |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.117 |