|
|
  |
Помогите освоить LUA |
|
|
sutra |
2.2.2019, 12:55
|
      
Adept
Сообщений: 923
Регистрация: 10.8.2018 Группа: Пользователи Наличность: 0
Пользователь №: 19.007

|
Резюмируя. Смотреть надо исключительно работу циклов, всё остальное, если и даёт прирост скорости, то настолько микроскопический, что нет смысла заниматься такими мелочами. Я вот переделал параметры на таблицу, там где у меня была строка - да, есть прирост, но мизерный. Грубо говоря, разброс результатов теста намного больше этого прироста скорости. Цитата Ну никак не мешает одно другому. Разве что часть математики по смещению адресов придется прописать в явном виде, а не полагаться на синтаксис, который проделает те же самые высчисления. Нет, всё. Больше не буду заморачиваться на таких мелочах. И так всё великолепно. Сейчас доделаю ещё одну примочку для цикла поиска и как минимум findcolor готов на 100% к "употреблению". (IMG: style_emoticons/default/smile.gif) Осталось сделать только анализ поиска НЕСКОЛЬКИХ картинок для findimage. Но что-то так лень, лично мне это не требуется, по крайней мере на текущий момент. А остальным вроде моя стряпня тоже не нужна, так что наверное на этом моё обучение закончено. Хотя я рекомендую тебе Дарк всё-таки посмотреть реализацию с использованием при поиске массива искомых пикселей, реально можно получить фантастический рывок по скорости в некоторых случаях (типа того же прицела).
|
|
|
|
sutra |
4.2.2019, 14:31
|
      
Adept
Сообщений: 923
Регистрация: 10.8.2018 Группа: Пользователи Наличность: 0
Пользователь №: 19.007

|
А в эфире - тишина. Видимо всё у всех работает как надо. А я вот НИЧЕГО не понимаю. Может кто научит как не надо делать?? Код с тестами
Код --lua local ffi=require "ffi" local rmem=ffi.cast ffi.cdef[[typedef struct{uint16_t x,y; uint8_t r,g,b;}xyrgb]] local function FindMemRGBf2(addr,len,fx1,fy1,fx2,fy2,usl,numf) -- ПОИСК ПИКСЕЛЕЙ ПО ЗНАЧЕНИЯМ RGB В ОБЛАСТИ ПАМЯТИ ===================================================================== -- addr,len : адрес в памяти, длина строки в памяти (то, что даёт getimage) -- fx1,fy1,fx2,fy2 : координаты поиска пикселей, относительно окна. -- usl : ОДНО условие поиска {[R=10,[R2=25,]] [G=70,[G2=100,]] [B=50,[B2=55,]] [RG=50,[RG2=150,]] [RB=-40,[RB2=-20,]] [GB=15,[GB2=15]] RG,RB,GB - разность между каналами; -- [numf] : максимальное количество искомых пикселей local lx,ly,r,g,b,p,d=fx2-fx1+1,fy2-fy1+1,ffi.new("uint8_t"),ffi.new("uint8_t"),ffi.new("uint8_t"),ffi.new("uint8_t[6]"),ffi.new("int16_t[6]") if numf then numf=math.min(numf,lx*ly) else numf=lx*ly end -- Ограничение параметра количества искомых пикселей до максимального возможного local arr,R,G,B,P,D,RG,RB,GB,k,i,j,ind=ffi.new("xyrgb[?]",numf),true,true,true,true,true,true,true,true,0,fy1 if usl.R then P,R,p[0],p[1]=false,false,usl.R,usl.R or usl.R2 end if usl.G then P,G,p[2],p[3]=false,false,usl.G,usl.G or usl.G2 end if usl.B then P,B,p[4],p[5]=false,false,usl.B,usl.B or usl.B2 end if usl.RG then D,RG,d[0],d[1]=false,false,usl.RG,usl.RG2 or 255 end if usl.RB then D,RB,d[2],d[3]=false,false,usl.RB,usl.RB2 or 255 end if usl.GB then D,GB,d[4],d[5]=false,false,usl.GB,usl.GB2 or 255 end if lx*3==len then ind=addr+fy1*len for i=ind,ind+ly*lx*3,3 do b,g,r=rmem("unsigned char*",i)[0],rmem("unsigned char*",i)[1],rmem("unsigned char*",i)[2] if(D or((RG or r-g>=d[0]and r-g<=d[1])and(RB or r-b>=d[2]and r-b<=d[3])and(GB or g-b>=d[4]and g-b<=d[5])))and(P or((R or r>=p[0]and r<=p[1])and(G or g>=p[2]and g<=p[3])and(B or b>=p[4]and b<=p[5])))then local c=math.floor((i-ind)/len) k,arr[k]=k+1,{x=(i-ind-c*len)/3,y=c,r=r,g=g,b=b} if numf==k then return k-1,arr end end end else while i<=fy2 do ind,j=addr+i*len+fx1*3,fx1 while j<=fx2 do b,g,r=rmem("unsigned char*",ind)[0],rmem("unsigned char*",ind)[1],rmem("unsigned char*",ind)[2] if(D or((RG or r-g>=d[0]and r-g<=d[1])and(RB or r-b>=d[2]and r-b<=d[3])and(GB or g-b>=d[4]and g-b<=d[5])))and(P or((R or r>=p[0]and r<=p[1])and(G or g>=p[2]and g<=p[3])and(B or b>=p[4]and b<=p[5])))then k,arr[k]=k+1,{x=j,y=i,r=r,g=g,b=b} if numf==k then return k-1,arr end end j,ind=j+1,ind+3 end i=i+1 end end return k-1,arr end---------------------------------------------------------------------------- local function FindMemRGBf3(addr,len,fx1,fy1,fx2,fy2,usl,numf) -- ПОИСК ПИКСЕЛЕЙ ПО ЗНАЧЕНИЯМ RGB В ОБЛАСТИ ПАМЯТИ ===================================================================== -- addr,len : адрес в памяти, длина строки в памяти (то, что даёт getimage) -- fx1,fy1,fx2,fy2 : координаты поиска пикселей, относительно окна. -- usl : ОДНО условие поиска {[R=10,[R2=25,]] [G=70,[G2=100,]] [B=50,[B2=55,]] [RG=50,[RG2=150,]] [RB=-40,[RB2=-20,]] [GB=15,[GB2=15]] RG,RB,GB - разность между каналами; -- [numf] : максимальное количество искомых пикселей local lx,ly,r,g,b,p,d=fx2-fx1+1,fy2-fy1+1,ffi.new("uint8_t"),ffi.new("uint8_t"),ffi.new("uint8_t"),ffi.new("uint8_t[6]"),ffi.new("int16_t[6]") if numf then numf=math.min(numf,lx*ly) else numf=lx*ly end -- Ограничение параметра количества искомых пикселей до максимального возможного local arr,R,G,B,P,D,RG,RB,GB,k,i,j,ind=ffi.new("xyrgb[?]",numf),true,true,true,true,true,true,true,true,0,fy1 if usl.R then P,R,p[0],p[1]=false,false,usl.R,usl.R or usl.R2 end if usl.G then P,G,p[2],p[3]=false,false,usl.G,usl.G or usl.G2 end if usl.B then P,B,p[4],p[5]=false,false,usl.B,usl.B or usl.B2 end if usl.RG then D,RG,d[0],d[1]=false,false,usl.RG,usl.RG2 or 255 end if usl.RB then D,RB,d[2],d[3]=false,false,usl.RB,usl.RB2 or 255 end if usl.GB then D,GB,d[4],d[5]=false,false,usl.GB,usl.GB2 or 255 end if lx*3==len then ind=addr+fy1*len i,j=ind,ind+ly*lx*3 -- ОТЛИЧИЕ ВСЕГО В 3-х строках ЭТА ИНИЦИАЛИЗАЦИЯ в принципе не может давать тормоза while i<=j do -- ОТЛИЧИЕ ВСЕГО В 3-х строках b,g,r=rmem("unsigned char*",i)[0],rmem("unsigned char*",i)[1],rmem("unsigned char*",i)[2] if(D or((RG or r-g>=d[0]and r-g<=d[1])and(RB or r-b>=d[2]and r-b<=d[3])and(GB or g-b>=d[4]and g-b<=d[5])))and(P or((R or r>=p[0]and r<=p[1])and(G or g>=p[2]and g<=p[3])and(B or b>=p[4]and b<=p[5])))then local c=math.floor((i-ind)/len) k,arr[k]=k+1,{x=(i-ind-c*len)/3,y=c,r=r,g=g,b=b} if numf==k then return k-1,arr end end i=i+3 -- ОТЛИЧИЕ ВСЕГО В 3-х строках end else while i<=fy2 do ind,j=addr+i*len+fx1*3,fx1 while j<=fx2 do b,g,r=rmem("unsigned char*",ind)[0],rmem("unsigned char*",ind)[1],rmem("unsigned char*",ind)[2] if(D or((RG or r-g>=d[0]and r-g<=d[1])and(RB or r-b>=d[2]and r-b<=d[3])and(GB or g-b>=d[4]and g-b<=d[5])))and(P or((R or r>=p[0]and r<=p[1])and(G or g>=p[2]and g<=p[3])and(B or b>=p[4]and b<=p[5])))then k,arr[k]=k+1,{x=j,y=i,r=r,g=g,b=b} if numf==k then return k-1,arr end end j,ind=j+1,ind+3 end i=i+1 end end return k-1,arr end---------------------------------------------------------------------------- -- 63638166 хендл рабочего окна do local p,w,h,l=getimage(0,0,1039,999,63638166) local k,arr log "clear" log "mode compact"
tmc=os.clock() for e=1,2000 do k,arr=FindMemRGBf3(p,l,0,0,1039,999,{R=255,G=235,B=98},1) end tmc=os.clock()-tmc log(tmc) -- 4.965 сек
tmc=os.clock() for e=1,2000 do k,arr=FindMemRGBf2(p,l,0,0,1039,999,{R=255,G=235,B=98},1) end tmc=os.clock()-tmc log(tmc) -- 3.376 сек !! В ПОЛТОРА РАЗА БЫСТРЕЕ
deleteimage(p) end -------------------------- тест второй рабочее окно то же самое do local p,w,h,l=getimage(0,0,1039,999) local k,arr
tmc=os.clock() for e=1,2000 do k,arr=FindMemRGBf3(p,l,0,0,1039,999,{R=255,G=235,B=98},1) end tmc=os.clock()-tmc log(tmc) -- 6.767 сек
tmc=os.clock() for e=1,2000 do k,arr=FindMemRGBf2(p,l,0,0,1039,999,{R=255,G=235,B=98},1) end tmc=os.clock()-tmc log(tmc) -- 6.741 сек
deleteimage(p) end stop_script()
Как всё это оптимизируется - одному Богу известно. Вопрос даже не в том, почему во второй раз медленнее, а в том почему в первом случае такая разница? Поменяйте тесты местами - тоже интересная картина получается. Сообщение отредактировал DarkMaster - 5.2.2019, 15:26
|
|
|
|
sutra |
4.2.2019, 16:40
|
      
Adept
Сообщений: 923
Регистрация: 10.8.2018 Группа: Пользователи Наличность: 0
Пользователь №: 19.007

|
Цитата В чем проблема уже сейчас переписать на том же Си и использовать как обычный подключаемый скрипт(только будет dll) через require() без каких-то заморочек ? Спасибо на добром слове, да кабы умел, давно бы сделал. Цитата Первый запуск тормозной - потом работает как обычная скомпилированная программа Может чего не понимаю, только у меня нет разницы между первым и последующими запусками. Конечно для подавляющего большинства случаев и так всё нормально работает, но есть у меня несколько узких моментов, вот и пытался допинать как умею. Конечно можно и на Делфи сделать, только у меня и там проблемы. 99% всего что я делал - делалось под консоль, опыт работы с библиотеками НУЛЕВОЙ. Надо сидеть и разбираться со всем этим. А вообще, спасибо за идею, наверное так и надо сделать. Один раз убить время и закончить заниматься этим маразмом.
|
|
|
|
sutra |
5.2.2019, 3:54
|
      
Adept
Сообщений: 923
Регистрация: 10.8.2018 Группа: Пользователи Наличность: 0
Пользователь №: 19.007

|
Цитата Перед выполенением код луа проходит компиляцию за исключением некоторых частных случаев Я всё понял (да и понимал с самого начала). Для меня нет разницы, когда компилируется, те доли секунды, что компилится мне безразличны ... картинки, массивы, конфигурация, сценарии, сценарии обработки сценариев грузятся ну как минимум на 2-3 порядка дольше. Мне важно, чтобы всё стабильно работало. Если сборка мусора будет происходить хаотично (пока не было реальных проблем) и выделение и очистка памяти будут работать как им вздумается (тут тебе меня надо поучить как этим управлять) то это конечно не очень хорошо. Просто у меня даже были участки кода (теперь их ликвидирую) которые считали не миллисекунды, а итерации выполнения циклов некоторых процессов (это было точнее), теперь я понял - это наверное неприемлемо. Цитата Нет возможности пока. Завтра надеюсь разгрести Так и не парься, я просто хотел для себя чуть-чуть понимать больше, чем я понимаю работу lua. А в целом всё нормально, считаю, что если не использовать более продвинутые технологии, мой несложный алгоритм вполне эффективен, скорости хватает. По крайней мере никто ничего нового или намного более эффективного не представил. Главное - работает и работает неплохо (благодаря тебе Дарк)!
|
|
|
|
Cockney |
5.2.2019, 12:44
|
       
Master
Сообщений: 1.404
Регистрация: 22.6.2013 Группа: Пользователи Наличность: 22594
Пользователь №: 16.156

|
Обозначим :
1)Работа пилота - это getimage, findcolor и т.п. функции которые уже готовы к использованию. Они скомпилированы и работают стабильно.
2)Lua - это все что пишет пользователь. Циклы, условия или другие функции. Компиляция этого добра происходит прямо перед запуском.
Тормозит цикл. А в каком месте ? Сам счетчик цикла тормозить не может, значит тормозит либо вызов функций пилота, либо пользовательской функции, либо тормозит математика написанная на lua.
Тут стоит посмотреть через профайлер точку, где происходит тормоз. Дальше уже от этого плясать нужно.
Средний срок развития компилятора до среднего уровня - 5 лет. Компилятору пилота - лет 20 минимум, компилятору lua - 14. Т.е. чтобы СВОЯ компиляция была лучше, нужно подождать еще лет 25-30.
Да и какой смысл ждать этого чуда, когда уже есть мощные инструменты, которые все подскажут и расскажут. Просто один раз написать dll обработки картинки и не ломать голову где тормоз.
|
|
|
|
sutra |
5.2.2019, 13:25
|
      
Adept
Сообщений: 923
Регистрация: 10.8.2018 Группа: Пользователи Наличность: 0
Пользователь №: 19.007

|
Я не про lua Код --lua tmc=os.clock() for i=1,2000 do local stN="123" end tmc=os.clock()-tmc log("Время : ",tmc) Время НУЛЬ - это откомпилировано Код set timer for #i 1 2000 set $stN "123" end_for log timer end_script
Время 0,1 сек. - это интерпретировано. Или я опять чего не понял? Сделать конечно же можно всё. Можно и без Пилота сделать программу (ежели конечно мозгов хватит). Пилот и нужен для таких как я - позволяет при минимуме знаний делать нужный результат. Для тех кто вообще не знаком с алгоритмированием - поможет автоматизировать некоторые действия. Для мастеров типа вас с Дарком - можно вообще всё. Я тут поразмыслил и решил ... а на кой мне это надо (я про dll). Ну пусть затормозило ... вместо 1 тысячной отработало за 2. Я уж просто припух и слишком многого хочу и так всё работает нормально. И всё что я тут наковырял назвать алгоритмом язык не поворачивается. Просто тупо подбирал параметры для ускорения работы, на мой взгляд, вполне неплохо подобрал. Этого будет достаточно.
|
|
|
|
DarkMaster |
5.2.2019, 15:23
|
          
Модератор UOPilot
Сообщений: 9.764
Регистрация: 2.12.2008 Группа: Супермодераторы Наличность: 29941
Пользователь №: 11.279

|
Цитата Сам счетчик цикла тормозить не может, значит тормозит либо вызов функций пилота, либо пользовательской функции, либо тормозит математика написанная на lua. Там фишка в том, что в lua есть jit. На высоконагруженных участках кода jit дает огромный выигрыш, но он непрогнозируемый от слова совсем. До того, что два вызова одной и той же функции с одними параметрами могут занять разное время. Компиляция lua происходит в два основных этапа: 1) Парсинг 2) Создание байт-блоков После чего в работу вступает jit. Он в реальном времени подсовывает необходимые байт-блоки и собирает, _пересобирает_ программу. Байт-блоки это не совсем та компиляция, которую мы представляем. Данные байт-блоки могут перемешиваться, компилироваться заново, перестраиваться. Байт-блок это по сути кусок программы откомпилированный стандартным образом. Т.е. у нас после компиляции выходит не один бинарник, а, скажем, 1000. После чего jit на основе _своей_ логики начинает управлять этими блоками. Чем прошаренее логика jit, тем больше ресурса она отжирает, но тем эффективнее работа смого приложения. Тут нужен некоторый баланс, который луа соблюдает. При этом очевидно, что в разных ситуациях один и тот же код может быть выполнен с разным набором байт-блоков: Пример 1: 1) был выполнен некоторый КОД_1 после которого структура байт-блоков находится в состоянии Х 2) jit проверяет пригодность данной конфигурации к следующему коду КОД_2 3) анализ сообщает, что перекомпановка займет 1мс, скорость выполнения увеличится на _50%_ 4) перекомпановка считается оправданной, байт-блоки пересобираются идеальным образом под новый код Пример 2: 1) был выполнен некоторый КОД_3 после которого структура байт-блоков находится в состоянии Y 2) jit проверяет пригодность данной конфигурации к следующему коду КОД_2 3) анализ сообщает, что перекомпановка займет 1мс, скорость выполнения увеличится на _5%_ 4) перекомпановка считается излишней, байт-блоки сохраняются в текущем виде. Таким образом скорость выполнения КОД_2 будет зависить то того выполнялся перед ним КОД_1 или КОД_3. Прогнозировать подобное поведение практически невозможно, тем не менее можно найти какие-то общие принципы наиболее критично влияющие на перекомпановку и собственно скорость выполнения кода. Сообщение отредактировал DarkMaster - 5.2.2019, 16:40
--------------------
Скрипты UOPilot под заказ. Консультации по UOpilot 15$/час. Услуги Lua разработчика (не пилот, проекты, постоянка) Disсоrd: Kov____
|
|
|
|
sutra |
11.2.2019, 13:33
|
      
Adept
Сообщений: 923
Регистрация: 10.8.2018 Группа: Пользователи Наличность: 0
Пользователь №: 19.007

|
Да, конечно по идее надо делать внешнюю функцию. Но мне самому наверное не сделать. Вот не знаю даже стоит ли просить помощи. Сегодня натолкнулся ну просто на непостижимые вещи. Решил чисто для интереса поподробнее потестировать свой файндимидж и обалдел. Пока толком не разбирался ГДЕ же наступают тормоза. Выполняется одно и то же в 2-х вариантах: 1) af=FindImage(..., 0,0,999,999, ...) - время поиска 0,415 сек. картинка находится по координатам 968 948 2) af=FindImage(..., 0,10,999,999, ...) - время поиска 0,016 сек. убавил всего 10 строк пикселей по оси Y - РАЗНИЦА АЖ В 25 раз. Менял выполнять код позже, раньше результат тот же.
Сильно изменяя код до вызова функций иногда получалось 0,1 сек. В общем "дикий" разброс по скорости. Всё-таки видимо это так криво сделан FOR. Надо вообще от него избавляться, думаю это он чудит.
|
|
|
|
|
  |
6 чел. читают эту тему (гостей: 6, скрытых пользователей: 0)
Пользователей: 0
|
|