PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Быстрый способ найти в списке прямоугольник, по координате.


Быстрый способ найти в списке прямоугольник, по координате.

Сообщений 31 страница 53 из 53

31

Более правильно сделал.
Ps:Ну да перебор от начала массива,да на асме проц так негрузится почему то у меня.
Ну и делать счёт count от 0 или 1 чтобы в процедурах поиска учесть этот момент (но это думаю не критично так как поиск основной в сравнении)

Код:

Structure koordinaty
X.i
Y.i
X1.i
Y1.i
EndStructure
Global count.i
Global Dim koordinaty.koordinaty(0)
Global Dim Stroka.s(0)

Procedure Set_object(count1)
  ReDim koordinaty.koordinaty(count1-1)
  ReDim Stroka.s(count1-1)
Protected i.i
count=count1
For i=0 To count-1
koordinaty(i)\X=i
koordinaty(i)\X1=i+100
koordinaty(i)\Y=i
koordinaty(i)\Y1=i+100
Stroka(i)=Str(i)
Next
EndProcedure


Procedure poisk(x,y)
If count>0
  For i=0 To count-1
    With koordinaty(i)
      If x>=\X And x<=\X1 And y>=\Y And y<=\Y1
        ProcedureReturn i
      EndIf
    EndWith
  Next
  ProcedureReturn -1
EndIf
EndProcedure
Procedure.i poisk2(*massiv.koordinaty,x,y,size);для теста 
  If size<1
    ProcedureReturn -1
  EndIf  
 Protected r.i=*massiv
size*16
size+*massiv
cikl:
If x>*massiv\X And x<*massiv\X1 And y>*massiv\Y And y<*massiv\Y1
  *massiv-r
  If *massiv=0
    ProcedureReturn *massiv
  Else  
   *massiv/16
   ProcedureReturn *massiv;index массива с 0
  EndIf
Else
     *massiv+16
  If *massiv<>size
    Goto cikl
  EndIf 
    ProcedureReturn -1
EndIf
EndProcedure

Procedure.i poisk3(*massiv,x,y,countt);для теста 
 !cmp dword  [p.v_countt],0
 !jz vyhod5
 ;
 !mov dword eax,[p.p_massiv]
 !sal dword [p.v_countt],4
 !add dword [p.v_countt],eax
 !mov dword ebx,[p.v_x]
 !mov dword edx,[p.v_y]
 !jmp r4555
!ckl777:
!add dword eax,16
!cmp dword eax,[p.v_countt]
!jz vyhod5
!r4555:
 !cmp dword ebx,[eax]
 !jl ckl777
 !cmp dword ebx,[eax+8]
 !jg ckl777
 !cmp dword edx,[eax+4]
 !jl ckl777
 !cmp dword edx,[eax+12]
 !jg ckl777
 !sub dword eax,[p.p_massiv]
 !cmp dword eax,0
 !jz f6544
 !sar dword eax,4
 !f6544:
 ProcedureReturn
 !vyhod5:
 ProcedureReturn -1
EndProcedure
Procedure.i poisk4(*massiv,x,y,countt);для теста 
 !mov dword ecx,[p.p_massiv]
 !xor  eax,eax
 !mov dword ebx,[p.v_x]
 !mov dword edx,[p.v_y]
 !jmp g8677
!vyhod134: 
  ProcedureReturn -1 
!ckl655:
 ;!add dword eax,1
 !inc eax
 
!cmp dword eax,[p.v_countt]
!jz vyhod134
!add dword ecx,16
!g8677:
;
 !cmp dword ebx,dword[ecx]
 !jl ckl655
 !cmp dword ebx,[ecx+8]
 !jg ckl655
 !cmp dword edx,[ecx+4]
 !jl ckl655
 !cmp dword edx,[ecx+12]
 !jg ckl655
;
 ProcedureReturn
EndProcedure


Set_object(10000000)


;Тест 1
TimeS.q = ElapsedMilliseconds()
  index.l= poisk(count+50,count+50)
ArrTime.q = ElapsedMilliseconds() - TimeS
MessageRequester("Тест","index  "+Str(index)+" stroka "+Stroka.s(index)+"  время теста  "+Str(ArrTime))

;Тест 2
TimeS.q = ElapsedMilliseconds()
  index= poisk2(@koordinaty(),count+50,count+50,count)
ArrTime.q = ElapsedMilliseconds() - TimeS
MessageRequester("Тест","index  "+Str(index)+" stroka "+Stroka.s(index)+"  время теста  "+Str(ArrTime))

;Тест 3
TimeS.q = ElapsedMilliseconds()
  index= poisk3(@koordinaty(),count+50,count+50,count)
ArrTime.q = ElapsedMilliseconds() - TimeS
MessageRequester("Тест","index  "+Str(index)+" stroka "+Stroka.s(index)+"  время теста  "+Str(ArrTime))
;Тест 4
TimeS.q = ElapsedMilliseconds()
  index= poisk4(@koordinaty(),count+50,count+50,count)
ArrTime.q = ElapsedMilliseconds() - TimeS
MessageRequester("Тест","index  "+Str(index)+" stroka "+Stroka.s(index)+"  время теста  "+Str(ArrTime))

Отредактировано Sergeihik (11.11.2022 10:36:57)

+1

32

Sergeihik написал(а):

Более правильно сделал.

Благодарю! По изучаю.
Я бы добавил ещё такую штуку, для x64:

Код:
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
  Macro eax : rax : EndMacro
  Macro ecx : rcx : EndMacro
CompilerEndIf

Но это так, к слову.

Отредактировано Webarion (11.11.2022 23:46:12)

0

33

Sergeihik написал(а):

Более правильно сделал.

Протестировал. Ни одна из ваших процедур, не находит элемент так, как необходимо. Я добавил процедуру для примера, которая делает то, что нужно. В следующем коде, её результат появляется первым:

Код:
Structure koordinaty
  X.i
  Y.i
  X1.i
  Y1.i
EndStructure

Global count.i
Global Dim koordinaty.koordinaty(0)
Global Dim Stroka.s(0)

Procedure Set_object(count1)
  ReDim koordinaty.koordinaty(count1-1)
  ReDim Stroka.s(count1-1)
  Protected i.i
  count=count1
  
  For i=0 To count-1
    With koordinaty(i)
    koordinaty(i)\X=i
    koordinaty(i)\X1=i+100
    koordinaty(i)\Y=i
    koordinaty(i)\Y1=i+100
    EndWith
    Stroka(i)=Str(i)
  Next
  
EndProcedure


;- ПРАВИЛЬНЫЙ ПОИСК
Procedure pravilnyj_poisk( x, y )
  For i=count-1 To 0 Step -1
    With koordinaty(i)
      If x>=\X And x<=\X1 And y>=\Y And y<=\Y1
        ProcedureReturn i
      EndIf
    EndWith
  Next
  ProcedureReturn -1
EndProcedure

Procedure poisk(x,y)
  If count>0
    For i=0 To count-1
      With koordinaty(i)
        If x>=\X And x<=\X1 And y>=\Y And y<=\Y1
          ProcedureReturn i
        EndIf
      EndWith
    Next
    ProcedureReturn -1
  EndIf
EndProcedure

Procedure.i poisk2( *massiv.koordinaty, x, y, size ) ; для теста 
  
  If size < 1
    ProcedureReturn -1
  EndIf
  
  Protected r.i = *massiv
  size * 16
  size + *massiv
  cikl:
  If x > *massiv\X And x < *massiv\X1 And y > *massiv\Y And y < *massiv\Y1
    *massiv-r
    If *massiv=0
      ProcedureReturn *massiv
    Else
      *massiv/16
      ProcedureReturn *massiv;index массива с 0
    EndIf
  Else
    *massiv+16
    If *massiv<>size
      Goto cikl
    EndIf 
    ProcedureReturn -1
  EndIf
EndProcedure

Procedure.i poisk3(*massiv, x, y, countt) ; для теста 
  !cmp dword  [p.v_countt], 0 ; если v_countt = 0     
  !jz vyhod5                  ; выходим
  ;
  !mov dword eax,[p.p_massiv] ; пишем в eax адрес массива countt
  !sal dword [p.v_countt],4   ; смещаем влево v_countt на 4 бита
  !add dword [p.v_countt],eax ; теперь eax в countt
  !mov dword ebx,[p.v_x]      ; x в ebx
  !mov dword edx,[p.v_y]      ; y и edx
  !jmp r4555
  !ckl777:
  !add dword eax,16
  !cmp dword eax,[p.v_countt]
  !jz vyhod5
  !r4555:
  !cmp dword ebx,[eax]
  !jl ckl777
  !cmp dword ebx,[eax+8]
  !jg ckl777
  !cmp dword edx,[eax+4]
  !jl ckl777
  !cmp dword edx,[eax+12]
  !jg ckl777
  !sub dword eax,[p.p_massiv]
  !cmp dword eax,0
  !jz f6544
  !sar dword eax,4
  !f6544:
  ProcedureReturn
  !vyhod5:
  ProcedureReturn -1
EndProcedure

Procedure.i poisk4(*massiv,x,y,countt) ; для теста 
  !mov dword ecx,[p.p_massiv]
  !xor  eax,eax
  !mov dword ebx,[p.v_x]
  !mov dword edx,[p.v_y]
  !jmp g8677
  !vyhod134: 
  ProcedureReturn -1 
  !ckl655:
  ;!add dword eax,1
  !inc eax
  
  !cmp dword eax,[p.v_countt]
  !jz vyhod134
  !add dword ecx,16
  !g8677:
  ;
  !cmp dword ebx,dword[ecx]
  !jl ckl655
  !cmp dword ebx,[ecx+8]
  !jg ckl655
  !cmp dword edx,[ecx+4]
  !jl ckl655
  !cmp dword edx,[ecx+12]
  !jg ckl655
  ;
  ProcedureReturn
EndProcedure


Set_object(10000000)

Define FindX = 3,  FindY = 3

;Тест с правильным нахождением
TimeS.q = ElapsedMilliseconds()
index.l= pravilnyj_poisk(FindX, FindY)
ArrTime.q = ElapsedMilliseconds() - TimeS
MessageRequester("Тест - правильное нахождение","index  "+Str(index)+" stroka "+Stroka.s(index)+"  время теста  "+Str(ArrTime))

;Тест 1
TimeS.q = ElapsedMilliseconds()
index.l= poisk(FindX, FindY)
ArrTime.q = ElapsedMilliseconds() - TimeS
MessageRequester("Тест","index  "+Str(index)+" stroka "+Stroka.s(index)+"  время теста  "+Str(ArrTime))

;Тест 2
TimeS.q = ElapsedMilliseconds()
index= poisk2(@koordinaty(), FindX, FindY, count)
ArrTime.q = ElapsedMilliseconds() - TimeS
MessageRequester("Тест","index  "+Str(index)+" stroka "+Stroka.s(index)+"  время теста  "+Str(ArrTime))

;Тест 3
TimeS.q = ElapsedMilliseconds()
index= poisk3(@koordinaty(), FindX, FindY, count)
ArrTime.q = ElapsedMilliseconds() - TimeS
MessageRequester("Тест","index  "+Str(index)+" stroka "+Stroka.s(index)+"  время теста  "+Str(ArrTime))

;Тест 4
TimeS.q = ElapsedMilliseconds()
index= poisk4(@koordinaty(), FindX, FindY, count)
ArrTime.q = ElapsedMilliseconds() - TimeS
MessageRequester("Тест","index  "+Str(index)+" stroka "+Stroka.s(index)+"  время теста  "+Str(ArrTime))

В принципе, я понял реализацию на ASM. Поэтому, по этой логике, достаточно, продолжать не стоит. Если будут другие идеи и алгоритмы, рад их исследовать.

Отредактировано Webarion (12.11.2022 05:41:51)

0

34

А какие алгоритмы кроме перебора?
Если вы ищете с конца и начала к середине то смысла нет,тот же перебор только инструкций больше процессору= меньше скоростть(пока дойдёшь до середины всё равно просканируешь весь массив<тоесть участок середины = участку конца поиска с начала)
Тогда уж проще разделить массив на попалам и в двух патоках поиск делать, но при 10000 тысячах стоит оно того?

0

35

Sergeihik написал(а):

А какие алгоритмы кроме перебора?
Если вы ищете с конца и начала к середине то смысла нет,тот же перебор только инструкций больше процессору= меньше скоростть(пока дойдёшь до середины всё равно просканируешь весь массив<тоесть участок середины = участку конца поиска с начала)
Тогда уж проще разделить массив на попалам и в двух патоках поиск делать, но при 10000 тысячах стоит оно того?

Тестами на ассемблере, ваша теория, не подтверждается. Во первых, у вас везде восходящий и неправильный поиск. Во вторых, индекс массива, это z координата, если вы ещё не поняли, что очень правильно описано в 1 посте. Я протестировал на ассемблере, ваш восходящий поиск, потом свой нисходящий, и убедился, что перекрёстный реверс быстрее, обоих этих алгоритмов. На счёт дополнительных потоков, уже писал. Повторяюсь, потоки долго инициализируются и на малых количествах элементов, оно того не стоит. Самый быстрый алгоритм перебора - встречный, от начала и с конца одновременно( т.е. так называемый перекрёстный реверс. Пример в начале ветки): Встречный поиск
Когда перебор происходит от первого элемента к последнему, придётся перебрать весь массив, чтобы определить верхний по указанным координатам. Напротив же, если перебор от последнего к первому, то выход происходит на первом верхнем найденном индексе. Но, если это уникальные координаты, которые касаются только первого созданного элемента, то в этом случае, также придётся перебрать весь массив. В отличии от этих двух вариантов, на встречный поиск затрачивается немного больше строк кода, но на тестах, он показывает лучший результат.
К тому же, поиск можно комбинировать с другими алгоритмами. Например с индексацией по сетке, это даёт колоссальный прирост скорости и контроль памяти: Индексация по сетке

Отредактировано Webarion (22.11.2022 01:31:53)

0

36

Ну какой встречный поиск без потоков ,ну сделай тест поиска на середине(координата,если поиск к середине) и посмотри как это скажется!
можно и рандом сделать но опять же замедлит это всё!
PS; вижу только на сопроцессоре увеличение скорости,но примеры надо искать(забыл нахрен)но подвигло это всё к написанию шпаргалки по асму,ну давно хотел(насколько интузиазма хватит?)

0

37

Sergeihik написал(а):

ну сделай тест поиска на середине

Уже давно делал. Не даёт это прироста. Пока процедура в дополнительном потоке запустится, поиск в основном, уже выполнен. На миллионах элементов, это ещё может прокатить.

Отредактировано Webarion (13.11.2022 00:00:09)

0

38

В общем по примеру Sergeihik, накидал на ассемблере, встречный поиск. Результат улучшился в 2 раза (для x32 пока):

Код:

Structure koordinaty
  X.i
  Y.i
  X1.i
  Y1.i
EndStructure

Global count.i
Global Dim koordinaty.koordinaty(0)
Global Dim Stroka.s(0)

Procedure Set_object(count1)
  ReDim koordinaty.koordinaty(count1-1)
  ReDim Stroka.s(count1-1)
  Protected i.i
  count=count1
  For i=0 To count-1
    With koordinaty(i)
      \X=i
      \X1=i+2
      \Y=i
      \Y1=i+2
    EndWith
    Stroka(i)=Str(i)
  Next
EndProcedure


;- обычный нисходящий поиск
Procedure _Search_Descending( x, y )
  For i=count-1 To 0 Step -1
    With koordinaty(i)
      If x>=\X And x<=\X1 And y>=\Y And y<=\Y1
        ProcedureReturn i
      EndIf
    EndWith
  Next
  ProcedureReturn -1
EndProcedure

;- обычный восходящий поиск
Procedure _Search_Ascending( x, y )
  Protected index = -1
  For i=0 To count-1
    With koordinaty(i)
      If x>=\X And x<=\X1 And y>=\Y And y<=\Y1
        index = i
      EndIf
    EndWith
  Next
  ProcedureReturn index
EndProcedure


; Встречный поиск для x32
Procedure _Search_CrossReverse_ASM( *massiv, x, y, countt )
  Protected search = -1

  !MOV dword ecx, [p.p_massiv] ; пишем в ecx адрес массива
  !MOV dword eax, ecx          ; eax = ecx
  !SAL dword [p.v_countt], 4   ; для правильной длины в памяти
  !ADD eax,  [p.v_countt]      ; eax в конец массива
  !SUB eax, 16                 ; на последний элемент
  
  !MOV dword ebx,[p.v_x]       ; x в ebx
  !MOV dword edx,[p.v_y]       ; y и edx  
  
  !JMP descending              ; прыгаем на первую проверку элемента
  
  !nextelement:
  !ADD dword ecx, 16           ; к следующему элементу  
  !SUB dword eax, 16           ; к предыдущему элементу 
  !CMP dword ecx, eax          ; сравниваем восходящий и нисходящий адреса
  !JGE ascending_exit          ; если встретились, то выходим
  
  ; проверяем по нисходящему адресу
  !descending:
  !CMP dword ebx,[eax]         ; сравнение x и x в памяти массива
  !JL  ascending               ; если первый < второго, переходим к проверке восходящего
  !CMP dword ebx,[eax+8]       ; и т.п.
  !JG  ascending
  !CMP dword edx,[eax+4]
  !JL  ascending
  !CMP dword edx,[eax+12] 
  !JG  ascending
  
  ; тут элемент найден
  !JMP descending_exit
  
  ; восходящий поиск
  !ascending:
  !CMP dword ebx,[ecx]        ; сравнение x и x в памяти массива
  !JL  nextelement            ; если первый < второго, переходим к следующему элементу
  !CMP dword ebx,[ecx+8]      ; и т.п.
  !JG  nextelement
  !CMP dword edx,[ecx+4]
  !JL  nextelement           
  !CMP dword edx,[ecx+12] 
  !JG  nextelement
  ; тут элемент найден, его нужно записать
  !MOV [p.v_search], ecx
  !JMP nextelement ; к следующему элементу
  
  !ascending_exit:
  !MOV eax, [p.v_search]
  !descending_exit:
  !SUB eax, [p.p_massiv]      ; вычисляем индекс массива, чтобы вернуть его
  !SAR dword eax,4

  ProcedureReturn
EndProcedure


If #PB_Compiler_Debugger
  Set_object(200000)
Else
  Set_object(10000000)
EndIf

;- ТЕСТ НИЖНЕГО
Define FindX = 1, FindY = 1
MessageRequester("Массив создан. Поиск в координатах: " + Str(FindX) + "," + Str(FindY), "Будем искать второй нижний элемент(дальний от последнего)" + #CRLF$ + "Ok - чтобы начать тестирование")


TimeS.q = ElapsedMilliseconds()
index = _Search_CrossReverse_ASM( @koordinaty(), FindX, FindY, count )
ArrTime.q = ElapsedMilliseconds() - TimeS
MessageRequester("Перекрёстный реверс ASM: " + Str(count) + " элементов","index  "+Str(index)+" stroka "+Stroka.s(index)+"  время теста  "+Str(ArrTime))

TimeS.q = ElapsedMilliseconds()
index= _Search_Descending( FindX, FindY )
ArrTime.q = ElapsedMilliseconds() - TimeS
MessageRequester("Нисходящий поиск: " + Str(count) + " элементов","index  "+Str(index)+" stroka "+Stroka.s(index)+"  время теста  "+Str(ArrTime))

TimeS.q = ElapsedMilliseconds()
index= _Search_Ascending( FindX, FindY )
ArrTime.q = ElapsedMilliseconds() - TimeS
MessageRequester("Восходящий поиск: " + Str(count) + " элементов","index  "+Str(index)+" stroka "+Stroka.s(index)+"  время теста  "+Str(ArrTime))


;- ТЕСТ ВЕРХНЕГО
FindX = count-2
FindY = count-2
MessageRequester("Поиск в координатах: " + Str(FindX) + "," + Str(FindY), "Будем искать второй верхний элемент (ближний к последнему)" + #CRLF$ + "Ok - чтобы начать тестирование")


TimeS.q = ElapsedMilliseconds()
index = _Search_CrossReverse_ASM( @koordinaty(), FindX, FindY, count )
ArrTime.q = ElapsedMilliseconds() - TimeS
MessageRequester("Перекрёстный реверс ASM: " + Str(count) + " элементов","index  "+Str(index)+" stroka "+Stroka.s(index)+"  время теста  "+Str(ArrTime))

TimeS.q = ElapsedMilliseconds()
index= _Search_Descending( FindX, FindY )
ArrTime.q = ElapsedMilliseconds() - TimeS
MessageRequester("Нисходящий поиск: " + Str(count) + " элементов","index  "+Str(index)+" stroka "+Stroka.s(index)+"  время теста  "+Str(ArrTime))

TimeS.q = ElapsedMilliseconds()
index= _Search_Ascending( FindX, FindY )
ArrTime.q = ElapsedMilliseconds() - TimeS
MessageRequester("Восходящий поиск: " + Str(count) + " элементов","index  "+Str(index)+" stroka "+Stroka.s(index)+"  время теста  "+Str(ArrTime))

Sergeihik написал(а):

вижу только на сопроцессоре увеличение скорости

Хотелось бы подробностей... и... кроссплатформенности  :shine:

Отредактировано Webarion (13.11.2022 10:32:31)

0

39

На интереснейший материал нарвался, по производительности кода: Ссылка на Хабр
Пусть будет. Это тоже часть исследования.

Отредактировано Webarion (13.11.2022 04:04:50)

0

40

Для x64 как то так регистры адресации 64 бита
Ну и метки поменять на другие

Код:
Procedure.i poisk3(*massiv,x,y,countt);для теста
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
;{;
 !cmp qword  [p.v_countt],0
 !jz vyhod56
 ;
 !mov qword rax,[p.p_massiv];64 битта стек и наш countt можно(поменять на тип Global count.q)
 !sal qword [p.v_countt],4
 !add qword [p.v_countt],rax
 !mov dword ebx,[p.v_x];как интегер 32бит(может быстрей поиск будет да и массив x,y.интегер)
 !mov dword edx,[p.v_y];
 !jmp r45556
!ckl7774:
!add qword rax,16
!cmp qword rax,[p.v_countt]
!jz vyhod5
!r45556:
 !cmp dword ebx,[rax]
 !jl ckl7774
 !cmp dword ebx,[rax+8]
 !jg ckl7774
 !cmp dword edx,[rax+4]
 !jl ckl7774
 !cmp dword edx,[rax+12]
 !jg ckl7774
 !sub qword rax,[p.p_massiv]
 !cmp qword rax,0
 !jz f65447
 !sar qword rax,4
 !f65447:
 ProcedureReturn
 !vyhod56:
 ProcedureReturn -1
;};
CompilerElseIf  #PB_Compiler_Processor = #PB_Processor_x86
;{;
 !cmp dword  [p.v_countt],0
 !jz vyhod5
 ;
 !mov dword eax,[p.p_massiv]
 !sal dword [p.v_countt],4
 !add dword [p.v_countt],eax
 !mov dword ebx,[p.v_x]
 !mov dword edx,[p.v_y]
 !jmp r4555
!ckl777:
!add dword eax,16
!cmp dword eax,[p.v_countt]
!jz vyhod5
!r4555:
 !cmp dword ebx,[eax]
 !jl ckl777
 !cmp dword ebx,[eax+8]
 !jg ckl777
 !cmp dword edx,[eax+4]
 !jl ckl777
 !cmp dword edx,[eax+12]
 !jg ckl777
 !sub dword eax,[p.p_massiv]
 !cmp dword eax,0
 !jz f6544
 !sar dword eax,4
 !f6544:
 ProcedureReturn
 !vyhod5:
 ProcedureReturn -1
 ;};
CompilerEndIf
EndProcedure

Отредактировано Sergeihik (13.11.2022 12:35:24)

0

41

Вот пример попробоал но тормозит жуть....

Код:
Procedure.i poisk5(*massiv,x,y,countt);для теста 
  Protected adres_1.i=1;для сложения
 !cmp dword  [p.v_countt],0
 !jz vuhod543
 !sub dword ptr p.v_countt,1;countt-1

!mov dword eax,[p.p_massiv]
; 
!XORPS xmm0,xmm0;обнулим xmm0
;!movss xmm1,dword ptr p.v_adres_1;xmm1=1,младший регистр[32 bit] остальные 96 бит=0
!movss xmm2,dword ptr p.v_x;загружает значение с плавающей запятой у нас как бы целое число
!movss xmm3,dword ptr p.v_y
!jmp ryrr43

!cikl74356:
!addss xmm0,dword ptr p.v_adres_1;xmm0+1
;!addss xmm0,xmm1;xmm0+1
;
!comiss xmm0,[p.v_countt];Скалярное сравнение с установкой eflags
!jz vuhod543
!add eax,16
;
!ryrr43:
 !comiss xmm2,[eax]
 !jl cikl74356
 !comiss xmm3,[eax+8]
 !jg cikl74356
 !comiss xmm2,[eax+4]
 !jl cikl74356
 !comiss xmm3,[eax+12]
 !jg cikl74356
;ок нашли
!movss dword [p.v_adres_1],xmm0;запишем индекс поиска
ProcedureReturn adres_1
!vuhod543:
ProcedureReturn -1
EndProcedure

0

42

Вообще бинарный поиск очень ускоряет - но время на вставку увеличивается, так как надо отсортировывать массив/список

0

43

Sergeihik написал(а):

Вот пример попробоал но тормозит жуть....

За пример спасибо, я его по изучаю. Там несколько строк надо добавить, чтобы это соответствовало условию задачи.
Смотри, у тебя в каждом примере кода, поиск ищет от начала к концу, и найдя первый нижний, происходит выход, что не верно, а надо искать самый верхний, соответствующий координатам.
Сергейчик, у меня к тебе просьба. Дело вот в чём. Все твои примеры, ни разу не выдали, тот результат, который соответствует поставленному условию. Напомню условие задачи из первого поста:

Webarion написал(а):

Первый созданный элемент, самый нижний, последний, самый верхний. Поэтому, если последний и первый находятся в указанных координатах, то должен быть найден последний.

Вообще, это убедительная просьба, к любому, кто заинтересуется этой задачей, а в этой ветке, был не вопрос, а приглашение. И некоторые участники, просто словами дали дельные советы. Так вот, прошу, в первую очередь прочитать внимательно и понять, о чём идёт речь.
Я приветствую примеры, но, только те, которые работают, и соответствуют поставленному условию. Только такие примеры, дают предпосылку к правильному изучению. Ну и к тому же позволяют не засорять обсуждение лишними постами.
Поэтому, ребят, ко всем обращаюсь. Если нет желания, никто не обидится. Я буду спокойно проводить исследование и периодически выдавать результат. Но, я всегда рад здравому диалогу и рабочим примерам кода, соответствующим, условию задачи. И приглашение было, делиться идеями. А если, что-то из предложенного, касается такой специфики, которую я не достаточно знаю, либо ещё не изучал, то тогда, я всегда прошу делиться примерами. Но, конечно такие примеры, я всегда буду тестировать, сравнивать и изучать.

Отредактировано Webarion (14.11.2022 01:29:49)

0

44

Артём написал(а):

Вообще бинарный поиск очень ускоряет - но время на вставку увеличивается, так как надо отсортировывать массив/список

Да!: вставка элемента, удаление, изменение координат, размеров, перемещение в другой уровень массива, всё это нужно. Но, для начала, в этой ветке, задан самый простой критерии обычного нахождения последнего созданного элемента, по заданным координатам. Начинаем с простого, хуже не будет, это хороший опыт:) Но в итоге, всё выше сказанное, в совокупности должно работать более-менее гармонично, и слажено по скорости, и памяти.  Предлагайте идеи, будем общаться, изучать)
Артём, примеру буду рад. Но перед этим, прошу прочитать и осознать моё сообщение на 1 выше)))

Отредактировано Webarion (14.11.2022 01:44:41)

0

45

Артём написал(а):

... так как надо отсортировывать массив/список

Моё мнение сейчас такое: массив да, список нет. Список работает иначе. Он индексируется и работает не так как массив. Поэтому, вставка в список не перелопачивет его весь в памяти. Это разные алгоритмы. Может быть, я ошибаюсь и нуб в этом вопросе, но в ассемблере при чтении памяти, я список не смог прочитать, точно так-же так как читается массив. Там другие алгоритмы.

Отредактировано Webarion (14.11.2022 02:06:19)

0

46

Ну так с последнего и ищите тогда,зачем первые смотреть вдруг следующий ближе к верху искомый?
Не два элемента же а сотни ,миллионы...........

Код:
Procedure.i Pt_Vmassive_Rect(*rect,x,y,countt)
                !push    ebp
                !mov     ebp,esp
                !mov     eax,[ebp+8]
                !test    eax,eax;есть адрес ?
                !jz      trghh;типа нет выходим
                !cmp dword [ebp+20],0
                !jz      trghh;типа countt=0
                !sal dword [ebp+20],4;countt*16
                ;!add dword [ebp+20],eax;поиск с начала
                !add dword eax,[ebp+20];поиск с конца
                ;
                !mov     ecx,[ebp+12];ecx=x
                !mov     ebx,[ebp+16];ecx=y
                !jmp trrty
               !cikl8655:
                ;!add dword eax,16;;поиск с начала
                ;!cmp dword eax,[ebp+20];поиск с начала
                !cmp dword eax,[ebp+8];=адресу *rect ?
                !jz trghh  
               !trrty:
                !sub dword eax,16;поиск с конца предварительно отнимем вначале цикла адрес -16 count=1 adres =+16 
                !cmp     ecx,[eax];x<*rect\x
                !jl      cikl8655
                !cmp     ecx,[eax+8];x>=*rect\x1
                !jg     cikl8655
                !cmp     ebx,[eax+4];y<*rect\y
                !jl   cikl8655
                !cmp     ebx,[eax+12];y>*rect\y1
                !jg     cikl8655
                ;
                !sub dword eax,[ebp+8];текущий адрес eax минус начальный *rect
                !jz gffgh;eax=0;если count=1 один элемент рамки то будет 0
                !sar dword eax,4;если больше то делим значение на 16 адресация массива рамок по 16 байт
               !gffgh:
               !pop     ebp
        ProcedureReturn ;результат поиска возвращается в eax
!trghh:
               !pop     ebp
        ProcedureReturn -1
EndProcedure

Отредактировано Sergeihik (14.11.2022 02:05:06)

-1

47

Sergeihik написал(а):

Ну так с последнего и ищите тогда

Всё уже найдено! Перекрёстный реверс на ассемблере быстрее дополнительного потока, а также восходящего и нисходящего перебора в том же асме. Повторюсь - ваша теория не подтвердилась в тестах.

Отредактировано Webarion (22.11.2022 02:17:01)

0

48

Sergeihik написал(а):

Ну так с последнего и ищите тогда,зачем первые смотреть вдруг следующий ближе к верху искомый?
Не два элемента же а сотни ,миллионы...........

Sergeihik, прошу тебя, покинуть этот чат, и больше никогда здесь не писать. Здесь, не нужны эгоисты, которые только себя и слышат. За ассемблер, я тебе отдельный + поставил, но большей пользы, от тебя, я не вижу. Убедительная просьба, в этой ветке, больше не появляться. Мне твой нерабочий код здесь не нужен.

Отредактировано Webarion (22.11.2022 02:12:31)

0

49

Это чегойто меня гонишь?
У меня вопрос вот наводящий а для чего вы в примере разноцветные объекты рисуете?

0

50

Sergeihik, не нужно игнорировать просьбу автора темы.

0

51

Пётр написал(а):

Sergeihik, не нужно игнорировать просьбу автора темы.

Ок покидаю ветку,я про цвет к тому что это тоже может быть идинтификатором к поиску,к примеру 10цветов на 10груп объектов соответственно прирост поиск под 10раз!
Да и тему он толком не раскрыл про нижний верхний,так как менять координаты собрался соответственно этот верхний допустим станет нижним или средним?
Ну да ладно дальше пусть другие думают.

Отредактировано Sergeihik (14.11.2022 13:07:29)

0

52

Sergeihik написал(а):

Это чегойто меня гонишь?
У меня вопрос вот наводящий а для чего вы в примере разноцветные объекты рисуете?

Я тебя не гнал, а попросил обоснованно, но услышал ли ты это?

Sergeihik написал(а):

Да и тему он толком не раскрыл про нижний верхний,так как менять координаты собрался соответственно этот верхний допустим станет нижним или средним?

Опять же, Sergeihik сам этого не понял. Объясню для других, но по моему, другие ответившие форумчане поняли всё правильно. При изменении координат, не меняется положение его z координаты(индекс массива), то есть он не становится более верхним или более нижним. Но, когда, мы захотим сделать его более верхним, или более нижним, да, придётся менять местами элементы массива. Но не более того. И здесь нет никакой проблемы, это элементарная операция.

Отредактировано Webarion (22.11.2022 03:36:46)

0

53

В общем ребят, я подумал и понял, что для обсуждения эту ветку пора закрывать. По большей части, в этом исследовании я всё понял.
В итоге, кто был полезен и чьи идеи я включу в первичную реализацию:
**> Моё подсознание: идея о перекрёстном реверсе. Реализовано на ассемблере и даёт более быстрый результат, чем другие поиски, как на ассемблере, так, и в нативе PB.
**> Пётр: идея запоминать текущий элемент списка. * Вторая идея Петра, ещё не подтверждена тестами, поэтому, сейчас это пока кандидат.
**> useful: идея об индексации. По предложенному SQLite, тесты не показали более быстрых результатов, но, за счёт этого, я придумал идею об индексации по квадратам сетки. Поэтому useful благодарочка! Человек дал хороший направляющий смысл.
**> Sergeihik: некоторые примеры кода на ассемблере (но не всю реализацию)
Все эти идеи, возможно будут реализованы в едином совместном коде.
Естественно, все авторы идей, будут упомянуты на тех версиях, к коду которых они причастны. Никто не будет забыт;)

Отредактировано Webarion (22.11.2022 03:26:41)

0


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Быстрый способ найти в списке прямоугольник, по координате.