|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Июн 29, 2003 16:33:44 · Поправил: Black_mirror Quantum Ты был прав, без цикла получается быстрее, только вот не понятно на сколько. Оба варианта написал на асме и вставил в код, замеряющий время(а не сделал их ввиде функций). Код для замера времени сказал что он выполнится за 11 тактов(rdtsc/mov ebx,eax/.../rdtsc). Этот код был заключен в цикл, который выполнял замер 65536 раз, и сохранял минимальный результат. Вариант без цикла(для подсчета бит) работал 51 такт, с циклом - 107. Проверял на eax=0ffffffffh. Затем выровнял метку для организации внешнего цикла, и метку во втором варианте. Первый вариант стал работать за 14(!!) тактов, а второй за 90. Вообщем я не понимаю прочему такая большая разница: 51 и 14 тактов ... Вернее не понимаю почему такая большая разника для кода в котором вообще нет переходов?! |
|
|
Дата: Июл 1, 2003 09:39:13 >... почему такая большая разника для кода в > котором вообще нет переходов?! Насколько мне позволяют судить мои скромные познания и опыт работы с конвеером, проц тормозит тогда, когда: 1) Он неправильно предсказывает переход; 2) Всегда лучше, когда условный переход редко выполняется, вот у Зубкова есть такой пример: ; Процедура rand ; возвращает в ЕАХ случайное положительное 32-; битное число ; (от 0 до 231-2) ; rand proc near push edx ; считать последнее случайное число mov eax,dword ptr seed ; проверить его, если это -1, test eax,eax ; функция еще ни разу не js fetch_seed ; вызывалась и надо создать ; начальное значение randomize: ; умножить на число а, mul dword ptr rand_a ; взять остаток от ; деления на 231-1 div dword ptr rand_m mov eax,edx ; сохранить для ; следующих вызовов mov dword ptr seed,eax pop edx ret fetch_seed: push ds push 0040h pop ds mov eax,dword ptr ds:006Ch ; считать ; двойное слово из области pop ds ; данных BIOS по адресу ; 0040:0060 - текущее число jmp short randomize ; тактов таймера Видимо, дело в этом ? |
|
|
Дата: Янв 2, 2004 05:10:43 Black_mirror А вот код для проверки попадает беззнаковое число в один из не пересекающихся интервалов [min1,max1), [min2,max2) Суперский пример! Оказывается, что интервалов может быть не только 2. Вот, кстати, немного изменённый пример для определения принадлежности байта к печатным цифрам и буквам (вроде IsAlphaNumeric(char x)): cmp al,'0'
sbb ah,ah
cmp al,'9' + 1
adc ah,0
cmp al,'A'
sbb ah,0
cmp al,'Z' + 1
adc ah,0
cmp al,'a'
sbb ah,0
cmp al,'z' + 1
adc ah,0 |
|
|
Дата: Янв 2, 2004 05:22:34 · Поправил: Quantum Или ещё лучше! Для любого количества интервалов: ; ============================================
; Params:
; AL - входной байт
; Return:
; Z - флаг снят, если AL принадлежит к
; одному из непересекающихся интервалов
; --------------------------------------------
multiint PROC SYSCALL uses esi
xchg al,dl
xor dh,dh
mov ecx,INTS_LEN
mov esi,OFFSET @ints
cld
@@: lodsw
cmp dl,al
sbb dh,0
cmp dl,ah
adc dh,0
loop @B
ret
@ints db '0','9' + 1 ; интервал 1 -> ['0', '9']
db 'A','Z' + 1 ; интервал 2 -> ['A', 'Z']
db 'a','z' + 1 ; интервал 3 -> ['a', 'z']
db '+','+' + 1 ; интервал 4 -> {'+'}
db '-','-' + 1 ; интервал 5 -> {'-'}
; и т.д.
INTS_LEN EQU ($ - @ints) / 2
multiint ENDP |
|
|
Дата: Янв 2, 2004 07:03:56 Quantum Твой код агрессивно пишет в партиальные регистры и поэтому страдает серьезной деградацией перфоманциi :) |
|
|
Дата: Янв 2, 2004 07:44:49 captain cobalt Разве сложно переделать под 32х-битные регистры? Можно даже не использовать LODSx, которая отрицательно сказывается на производительности. Зато в предоставленном виде код более читабельный. |
|
|
Дата: Янв 2, 2004 08:19:01 Хм... Ну... Если просят код дзена, то наверное имеет смысл СНАЧАЛА обработать напильником, а потом показывать народу. Смотри, другие клочки кода в этом треде отнюдь не являются самодокументированными... А код действительно работает... :) Только, возможно, следует читать: "флаг Z установлен если НЕ принадлежит" |
|
|
Дата: Янв 2, 2004 14:19:28 · Поправил: S_T_A_S_ Еще один вариант интервалы '0' - '9' и 'A' - 'F' mov CL, value sub CL, '0'-1 ;-----------0123456789:;<=>?@ABCDEFGHIJKLMNO mov EAX, 11111111110000000111111000000000y shl EAX, CL jc hex |
|
|
Дата: Янв 2, 2004 21:39:11 Ещё вариант для случая, когда диапазон большой и интервалов много: В отсортированном по возрастанию массиве границ интервалов находится количество элементов меньше проверяемого. Проверяемый элемент попадает в интервал если это количество нечетное. При этом интервалы проверяются не все, а только до нужного. Если их очень много, то можно и двоичный поиск применить. Дополнительно, на халяву имеется номер найденного интервала (количество пересеченных границ пополам) и его начало. В общем, что-то вроде этого: ; на входе: eax - проверяемое значение ; на выходе: carry flag - входит или нет, ebx - номер интервала findint: xor ebx,ebx .search: cmp eax,[ints+ebx] jae .found inc ebx cmp ebx,ints.len jb .search .found: shr ebx,1 ret ints dd '0','9'+1,'A','F'+1,'a','f'+1 .len equ $-intsНабрано прямо здесь, проверять или оптимизировать лень. ;) |
|
|
Дата: Янв 2, 2004 21:54:16 captain cobalt Если просят код дзена, то наверное имеет смысл СНАЧАЛА обработать напильником, а потом показывать народу. А оптимизация по размеру разве дзеном не является? Почему ты решил, что я не обработал этот код предварительно напильником? И вообще, данный код основан на примере by Black_mirror, так что совсем моим я его назвать не могу. Только, возможно, следует читать: "флаг Z установлен если НЕ принадлежит" Исправил. S_T_A_S_ bsl_zcs Записываю! :-) |
|
|
Дата: Янв 2, 2004 23:18:19 |
|
|
Дата: Янв 3, 2004 00:24:06 bsl_zcs > Ещё вариант для случая, когда диапазон большой и интервалов много а на этот случай есть структуры данных под названием деревья промежутков (interval tree) |
|
|
Дата: Янв 3, 2004 03:06:04 S_T_A_S_ Спасибо за ссылку! captain cobalt Если интервалы отсортированы и использовать бинарный поиск, то вариант bsl_zcs будет не хуже поиска по дереву. Принцип в обоих случаях тотже. |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.087 |