· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.A&O —› Str_to_Int

<< . 1 . 2 . 3 . 4 . >>

Посл.отвђт Сообщен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:56

c3ah 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 лишнее слово

<< . 1 . 2 . 3 . 4 . >>


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.117