На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
[!] Как относитесь к модерированию на этом форуме? Выскажите свое мнение здесь
Модераторы: Qraizer
Страницы: (3) 1 [2] 3  все  ( Перейти к последнему сообщению )  
> Нужен быстрый алгоритм сравнение строк...
    Согласен с Flex Ferrum насчет того, что скорее всего действительно придется переписать на асме, но для начала все-таки неплохо бы выбрать наилучший алгоритм.
    Сравнивать строки в лоб - слабая опримизация, не так ли?
    Что у тебя будет происходить: сравнение миллионов строк или миллионы сравнений ограниченного количества строк? Во втором случае имхо подошла бы стратегия построения для каждой строки хэша.
    Все-таки сравнивать хэши на неравенство поэффективнее будет.
      2Valery: Да именно так... ошибся...
      2ALL: Да мне нужен алгоритм... а написать я и на асме смогу и на сях..
      -----------
      Там просто есть какието битовые алгоритмы сравнения и на скока я знаю они быстрее всего работают...
        Sourcer:
        Не мути воду. Команда rep cmpsb будет работать заведомо быстрее любого битового алгоритма, если таковые существуют. Есть отдельный класс алгоритмов для посика подстрок в строке - это да. Но элементарной сравнение двух строк - это врядли. И действительно, поясни, что тебе нужно - сравнение одной строки со множеством других, или просто сравнение разных строк? Если первый случай, то, действительно, как предложил Valery, считай для строки Hash (например, CRС), после чего сравнивай их значения. Работать будет как из пушки. К томуже, если ты эти CRC еще и в деревце сбалансированное сложишь - то вообще будет супер.
          если тебе нужно сравнить сотни тысяч или миллионы строк, то алгоритм сравнения будет занимать малую часть времени. тебе нужно обеспечить быстрый доступ к строкам.
          кроме того, эффективность алгоритма будет зависить от длины строк.
          если строки в несколько байт длиной, то эффективнее далать через MMX. к тому же комманды MMX выполняются параллельно с другими командами.
            при использовании
            repe cmpsb
            нет необходимости высчитывать длины строк, сравнение будет закончено если найден ноль или разные байты.
            можно попробовать
            repe cmpsw
            или
            repe cmpsd
            сравниваться будут сразу соответственно два или четыре байта. в конец строки при этом придется записать не менее трех нулевых байт(для cmpsw) или семи нулевых байт (для cmpsd)
              вот-с:
              _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 :)
                тут в исходнике небольшая ошибочка - после dec ecx;
                надо поставить
                jz _exit;
                  Если строки хранить в виде дерева, то скорость поиска нужной строки не будет зависить от количества исходных строк.
                  В каждом узле дерева символ строки либо символ конца строки. Из узла указатель(указатели) на следующий символ.
                  Это дерево позволит организовать самый быстрый алгоритм поиска, и разница С/asm здесь уже не существенна.
                    Надо что-то типа этого:
                    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);
                    }
                      Только перед тем как в строки записывать данные желательно забить памят под неё нулями, хотябы 4 нуля (включая признак конца строки).
                      На самомо деле какой из алгоритмов самый быстрый будет зависить от конкретного случая, и выбирая алгоритм надо опираться на некоторую предположительную информацию о содержимом строк.
                        2VuDZ:
                        Чего-то команду "prefetcht0" мой VC6 никак не признает. Может подкинешь бинарный кодик для строк с ее использованием (prefetcht0 [esi + ecx * 8 - 64] и т.д.) ?
                          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;
                          }
                            2x - pcmpeqd, prefetcht0 - это не ММХ?
                              ах, да, забыл....
                              это SSE :D
                                кстати, я тоже думал, что rep cmpsd быстрее, чем rep cmpsb, но после долгих сравнений обнаружил, что rep cmpsd в 4 раза медленнее... почему?
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (3) 1 [2] 3  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0431 ]   [ 16 queries used ]   [ Generated: 27.04.24, 19:53 GMT ]