Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.15.218.254] |
|
Страницы: (3) 1 [2] 3 все ( Перейти к последнему сообщению ) |
Сообщ.
#16
,
|
|
|
Согласен с Flex Ferrum насчет того, что скорее всего действительно придется переписать на асме, но для начала все-таки неплохо бы выбрать наилучший алгоритм.
Сравнивать строки в лоб - слабая опримизация, не так ли? Что у тебя будет происходить: сравнение миллионов строк или миллионы сравнений ограниченного количества строк? Во втором случае имхо подошла бы стратегия построения для каждой строки хэша. Все-таки сравнивать хэши на неравенство поэффективнее будет. |
Сообщ.
#17
,
|
|
|
2Valery: Да именно так... ошибся...
2ALL: Да мне нужен алгоритм... а написать я и на асме смогу и на сях.. ----------- Там просто есть какието битовые алгоритмы сравнения и на скока я знаю они быстрее всего работают... |
Сообщ.
#18
,
|
|
|
Sourcer:
Не мути воду. Команда rep cmpsb будет работать заведомо быстрее любого битового алгоритма, если таковые существуют. Есть отдельный класс алгоритмов для посика подстрок в строке - это да. Но элементарной сравнение двух строк - это врядли. И действительно, поясни, что тебе нужно - сравнение одной строки со множеством других, или просто сравнение разных строк? Если первый случай, то, действительно, как предложил Valery, считай для строки Hash (например, CRС), после чего сравнивай их значения. Работать будет как из пушки. К томуже, если ты эти CRC еще и в деревце сбалансированное сложишь - то вообще будет супер. |
Сообщ.
#19
,
|
|
|
если тебе нужно сравнить сотни тысяч или миллионы строк, то алгоритм сравнения будет занимать малую часть времени. тебе нужно обеспечить быстрый доступ к строкам.
кроме того, эффективность алгоритма будет зависить от длины строк. если строки в несколько байт длиной, то эффективнее далать через MMX. к тому же комманды MMX выполняются параллельно с другими командами. |
Сообщ.
#20
,
|
|
|
при использовании
repe cmpsb нет необходимости высчитывать длины строк, сравнение будет закончено если найден ноль или разные байты. можно попробовать repe cmpsw или repe cmpsd сравниваться будут сразу соответственно два или четыре байта. в конец строки при этом придется записать не менее трех нулевых байт(для cmpsw) или семи нулевых байт (для cmpsd) |
Сообщ.
#21
,
|
|
|
вот-с:
_asm{ mov edi, p2; mov esi, p1; mov ecx, 16777216; // или из переменной shr ecx, 3; // деление на 8 dec ecx; // уменьшение для первого сравнения lp: movq mm0, [edi + ecx * 8]; // тут сррока №1 movq mm1, [esi + ecx * 8]; // тут строка №2 dec ecx; pcmpeqd mm0, mm1; // сравнение сразу 8 байт // если хоть один отличен - всё - одни 0 // иначе везде ff movd eax, mm0; // грузим всё это в eax prefetcht0 [esi + ecx * 8 - 64] test al, al; // и тестим на 0 jz stp; // если 0 - всё, строки различены prefetcht0 [edi + ecx * 8 - 64] // иначе до упора jnz lp; stp: // тут мона ставить некий флажок или ещё что-то } _asm emms; // нужно обязательно в три раза быстрее strcmp() и в 2 чем вариант Flex Ferrum'a... Just use this |
Сообщ.
#22
,
|
|
|
тут в исходнике небольшая ошибочка - после dec ecx;
надо поставить jz _exit; |
Сообщ.
#23
,
|
|
|
Если строки хранить в виде дерева, то скорость поиска нужной строки не будет зависить от количества исходных строк.
В каждом узле дерева символ строки либо символ конца строки. Из узла указатель(указатели) на следующий символ. Это дерево позволит организовать самый быстрый алгоритм поиска, и разница С/asm здесь уже не существенна. |
Сообщ.
#24
,
|
|
|
Надо что-то типа этого:
int find_str(char* buf1,char* buf2,int len1,int len2) { int* i1=(int *)buf1; int* i2=(int *)buf2; register int t=0; register int l; if (len1<len2) l=len1/4; else l=len2/4; while ((i1[t]==i2[t])&(t<=l)) t++; return(t>l); } |
Сообщ.
#25
,
|
|
|
Только перед тем как в строки записывать данные желательно забить памят под неё нулями, хотябы 4 нуля (включая признак конца строки).
На самомо деле какой из алгоритмов самый быстрый будет зависить от конкретного случая, и выбирая алгоритм надо опираться на некоторую предположительную информацию о содержимом строк. |
Сообщ.
#26
,
|
|
|
2VuDZ:
Чего-то команду "prefetcht0" мой VC6 никак не признает. Может подкинешь бинарный кодик для строк с ее использованием (prefetcht0 [esi + ecx * 8 - 64] и т.д.) ? |
Сообщ.
#27
,
|
|
|
LOL
чего MMX никто не вспомнил? кусок моей либы BOOL CompareRowB(void *dest, void *src, DWORD size) { BOOL rtn=TRUE; DWORD sz=size; _asm{ pushad mov esi,src mov edi,dest mov ecx,sz cld rep cmpsb jz cmrqb //jmp quit if *src==*dest mov rtn,FALSE cmrqb: emms popad } return rtn; } BOOL CompareRowW(void *dest, void *src, DWORD size) { BOOL rtn=TRUE; DWORD sz=size; _asm{ pushad mov esi,src mov edi,dest mov ecx,sz cld rep cmpsw jz cmrqw //jmp quit if *src==*dest mov rtn,FALSE cmrqw: emms popad } return rtn; } BOOL CompareRowD(void *dest, void *src, DWORD size) { BOOL rtn=TRUE; DWORD sz=size; _asm{ pushad mov esi,src mov edi,dest mov ecx,sz cld rep cmpsd jz cmrqd //jmp quit if *src==*dest mov rtn,FALSE cmrqd: emms popad } return rtn; } BOOL CompareRowQ(void *dest, void *src, DWORD size) { BOOL rtn=TRUE; DWORD sz=size; _asm{ pushad xor eax,eax movd mm2,eax mov edx,0xFFFFFFFF mov esi,src mov edi,dest mov ecx,sz mov ebx,8 cld crql: movq mm0,[esi] add esi,ebx movq mm1,[edi] add edi,ebx pcmpeqd mm0,mm1 packuswb mm0,mm2 movd eax,mm0 cmp eax,edx jnz cmrqb dec ecx jz crql //jmp quit if *src==*dest jmp cmrqb mov rtn,FALSE cmrqb: emms popad } return rtn; } BOOL CompareRowFastB(void *dest, void *src, DWORD size) { if (size==0) return FALSE; if (size>8) { if (CompareRowFastQ(dest,src,size>>3)) return TRUE; if (CompareRowB((void*)((DWORD)dest+((size>>3)<<3)),(void*)((DWORD)src+((size>>3)<<3)),size\%8)) return TRUE; } else return CompareRowB(dest,src,size); return FALSE; } BOOL CompareRowFastW(void *dest, void *src, DWORD size) { if (size==0) return FALSE; if (size>4) { if (CompareRowFastQ(dest,src,size>>2)) return TRUE; if (CompareRowW((void*)((DWORD)dest+((size>>2)<<3)),(void*)((DWORD)src+((size>>2)<<3)),size\%4)) return TRUE; } else return CompareRowW(dest,src,size); return FALSE; } BOOL CompareRowFastD(void *dest, void *src, DWORD size) { if (size==0) return FALSE; if (size>2) { if (CompareRowFastQ(dest,src,size>>1)) return TRUE; if (CompareRowD((void*)((DWORD)dest+((size>>1)<<3)),(void*)((DWORD)src+((size>>1)<<3)),size\%2)) return TRUE; } else return CompareRowD(dest,src,size); return FALSE; } BOOL CompareRowFastQ(void *dest, void *src, DWORD size) { if (size==0) return FALSE; if (((DWORD)src\%8!=0) && (size>1)) { //align src if (CompareRowQ(dest,src,1)) return TRUE; if (CompareRowQ((void*)((DWORD)dest+8-((DWORD)src\%8)),(void*)((DWORD)src+8-((DWORD)src\%8)),size-1)) return TRUE; if (CompareRowB((void*)((DWORD)dest+(size-1)*8),(void*)((DWORD)src+(size-1)*8),(DWORD)src\%8)) return TRUE; } else return CompareRowQ(dest,src,size); return FALSE; } |
Сообщ.
#28
,
|
|
|
2x - pcmpeqd, prefetcht0 - это не ММХ?
|
Сообщ.
#29
,
|
|
|
ах, да, забыл....
это SSE |
Сообщ.
#30
,
|
|
|
кстати, я тоже думал, что rep cmpsd быстрее, чем rep cmpsb, но после долгих сравнений обнаружил, что rep cmpsd в 4 раза медленнее... почему?
|