|
|
  |
Помогите освоить LUA |
|
|
DarkMaster |
13.11.2018, 2:17
|
          
Модератор UOPilot
Сообщений: 9.764
Регистрация: 2.12.2008 Группа: Супермодераторы Наличность: 29941
Пользователь №: 11.279

|
Цитата Да и игры заточены только на выманивание денег - интеллекта - нуль целых, хрен десятых. Вот поэтому я играю последнее время и игры 90-х, начала 2000, когда ресурсы уже позволяли сделать что-то удобоваримое, а качество еще встречалось. Кстати говоря неплохие проекты есть и сейчас, причем они как правило DRM-free и распространяются через gog. Могу предложить взглянуть на RimWorld, Pillars of Eternity (играл только в первый). Цитата А вот это не факт. Чаще всего использую в блокноте (notepad++) когда обычным поиском бывает неудобно. Цитата Это раньше за каждый байт и даже бит "бились". Я работал на Искре-1030 (512 кб оперативки, 10 МБ разбитый на 5 лог. дисков винт) приходилось некоторые участки кода на ассемблере писать. А сейчас ... кто на чём будет экономить? Сейчас тоже не все так просто. Просто сами операции зачастую очень невменяемые с точки зрения программиста. Например, распознавание текста на экране с помощью анализа изображения. А иногда приходится делать именно вот так вот. Причем как раз в этих ситуациях очень сильно аукается jpg со своим рендерингом. Приходилось делать до 300 изображений букв и это давало не 100% результат, но приемлимый для отбраковки. Такое количество анализа неизбежно тратит очень большое количество тактов и время работы программы увеличивается до превышающее допустимое. Приходится оптимизировать и выкрадывать каждый пиксель, прогозировать смещения, вместо распознавания фразы начинать распознавать буквы и предугадывать возможные ветвления. Узкие места всегда есть. Но тут уже специфика задачи не позволяет просто взять и считать значение из памяти.
--------------------
Скрипты UOPilot под заказ. Консультации по UOpilot 15$/час. Услуги Lua разработчика (не пилот, проекты, постоянка) Disсоrd: Kov____
|
|
|
|
sutra |
13.11.2018, 15:36
|
      
Adept
Сообщений: 923
Регистрация: 10.8.2018 Группа: Пользователи Наличность: 0
Пользователь №: 19.007

|
Не поленился и потестил чутка некоторые вещи. local ss="" local handle=windowhandle() local tmm = os.clock() for i=1,100000 do ss=readmem(address,"s",255,handle) end log(os.clock()-tmm) -- Время теста 15.511 - 16.245 секунд Меняем строку цикла ss=readmem(address,"s",1,windowhandle()) Время теста 30.214 - 30.931 секунд tmm = os.clock() for i=1,200 do bmp=FindRGB (address, len, x1, y1, x2, 49,402,51,901,"R(0-255)",20000) end log(os.clock()-tmm) --Время теста 16.083 - 16.153 секунд (ровно 100000 вызовов reedmem) local tmm = os.clock() for i=1,50000 do bmp=FindRGB (address, len, x1, y1, x2, 41,900,51,901,"R(0-255)",20000) end log(os.clock()-tmm) -- Время теста 24,215 Тот же тест, но я убрал из функции local handle=windowhandle() поместив его в тело скрипта Время теста 16.151 Вывод очевиден всё родное даже не подлежит тестированию, потому что любая внешняя функция кушает несопоставимо больше. Следовательно нужно стремиться к минимизации вызовов внешних функций, остальное в расчёт можно не брать. Опять же без разницы что там выполняет внешняя функция, чисто сам факт её вызова приводит lua в ступор. Цитата распознавание текста Я конечно не спец по этому вопросу. Но применительно к Пилоту и lua я этот вопрос решил. Мне же не нужно писать свой файнридер. Я знаю точно какой шрифт распознаю. По реперным точкам колором в lua - это делается мгновенно. Раньше в Пилоте были проблемы, а в lua for и if просто летают. Собственно почему мне и нужен анализ цветовой разницы каналов. Сделал скрин и "вылизываю" его как хочу. Свой имидж на анализ 800 файлов я делал когда не было lua. Пока работает мой имидж джипеговский мне переделывать лень, процесс долгий, пока ещё вычислишь все цветовые значения реперных точек.
|
|
|
|
sutra |
17.11.2018, 15:18
|
      
Adept
Сообщений: 923
Регистрация: 10.8.2018 Группа: Пользователи Наличность: 0
Пользователь №: 19.007

|
Дарк, спасибо, разобрался с ридмемом, вроде всё работает. Но вопрос у меня есть. Ходил на ссылочку которую ты дал по использованию СИ структур. Вопрос собственно вот в чём, можно и если можно то как описать структуру из 5-ти элементов {x, y, red, green, blue}
В примере так, но мне тут не всё понятно local ffi = require("ffi") ffi.cdef[[ typedef struct { uint8_t red, green, blue, alpha; } rgba_pixel; ]] uint8_t - это что-то типа 8 бит? rgba_pixel - а это зарезервированный тип или просто имя структуры?
local img = ffi.new("rgba_pixel[?]", n)
Это в примере инициализация, я правильно понял, что n - это заранее объявленный размер массива?
rgba_pixel[?] - а вот про знак вопроса - это не совсем понял.
|
|
|
|
sutra |
17.11.2018, 16:43
|
      
Adept
Сообщений: 923
Регистрация: 10.8.2018 Группа: Пользователи Наличность: 0
Пользователь №: 19.007

|
А вообще не трать время Дарк, всё и так просто летает, вызов моего файнда, затрачивает на 28000 элементов массива найденных пикселей 1 тысячную секунды. Для меня результат более чем ... Просто раньше стремился минимизировать вызовы файнда, поэтому и массивы результирующие были побольше, теперь ридмем выполняется мгновенно, следовательно можно крутить файндом сколько угодно. Спасибо тебе огромное Дарк, такую проблему помог решить. Если кому надо пользуйтесь, может ошибки найдёте. Код function FindRGB(addr,len,scrX1,scrY1,fx1,fy1,fx2,fy2,usl,numf) -- Функция поиска RGB в области памяти -- addr,len : адрес в памяти и длина строки в памяти (те, что даёт getimage) -- scrX1,scrY1 : координаты верхнего левого угла скрина в памяти, аналогичны координатам getimage (конечные X и Y не требуются) -- fx1,fy1,fx2,fy2 : координаты поиска, абсолютные относительно рабочего окна. Обязательно должны быть внутри диапазона скрина. -- usl : условие поиска ОДНО, по принципу ужесточения параметров "R(0-255) G(70-90) B(50) R-G[10 80] R-B[-40 -20] G-B[15]" (G-B[15] идентично G-B[15 255] -- разность между каналами с возможностью интервала) -- numf : максимальное количество искомых пикселей local rmem = require "ffi".cast local _,_,r1,r2=usl:find("R%((%d+)%-*(%d*)") r1,r2=tonumber(r1),tonumber(r2) -- Получение синтаксических значений поиска по каналу RED local _,_,g1,g2=usl:find("G%((%d+)%-*(%d*)") g1,g2=tonumber(g1),tonumber(g2) -- Получение синтаксических значений поиска по каналу GREEN local _,_,b1,b2=usl:find("B%((%d+)%-*(%d*)") b1,b2=tonumber(b1),tonumber(b2) -- Получение синтаксических значений поиска по каналу BLUE local _,_,RG1,RG2=usl:find("R%-G%[(%-*%d+)%s*(%-*%d*)") RG1,RG2=tonumber(RG1),tonumber(RG2) local _,_,RB1,RB2=usl:find("R%-B%[(%-*%d+)%s*(%-*%d*)") RB1,RB2=tonumber(RB1),tonumber(RB2) local _,_,GB1,GB2=usl:find("G%-B%[(%-*%d+)%s*(%-*%d*)") GB1,GB2=tonumber(GB1),tonumber(GB2) if r1==nil then r1,r2=0,255 else if r2==nil then r2=r1 end end if g1==nil then g1,g2=0,255 else if g2==nil then g2=g1 end end if b1==nil then b1,b2=0,255 else if b2==nil then b2=b1 end end if RG1==nil then RG1,RG2=-255,255 else if RG2==nil then RG2=255 end end if RB1==nil then RB1,RB2=-255,255 else if RB2==nil then RB2=255 end end if GB1==nil then GB1,GB2=-255,255 else if GB2==nil then GB2=255 end end local arr,k,indY,ind,r,g,b={},0 for i=fy1,fy2 do indY=addr+(i-scrY1)*len for j=fx1,fx2 do ind=indY+(j-scrX1)*3 b=rmem("unsigned char*", ind)[0] g=rmem("unsigned char*", ind+1)[0] r=rmem("unsigned char*", ind+2)[0] if r>=r1 and r<=r2 and g>=g1 and g<=g2 and b>=b1 and b<=b2 and r-g>=RG1 and r-g<=RG2 and r-b>=RB1 and r-b<=RB2 and g-b>=GB1 and g-b<=GB2 then k=k+1 arr[k]={} arr[k][1]=j arr[k][2]=i arr[k][3]=r arr[k][4]=g arr[k][5]=b if numf<=k then return arr end end end end return arr end
|
|
|
|
DarkMaster |
17.11.2018, 20:40
|
          
Модератор UOPilot
Сообщений: 9.764
Регистрация: 2.12.2008 Группа: Супермодераторы Наличность: 29941
Пользователь №: 11.279

|
Цитата uint8_t - это что-то типа 8 бит? Это типа условно новые стандарты старых понятий. Unsignet int 8 bit _ type, если расшифровать. Т.е. это беззнаковое число 8 бит, прямое указание на то, что это тип, а не функция или еще что-нибудь. Конкретно в данном случае отличий от char в реалиях не будет, но теоретически char может быть больше 8 бит (он регламентирован, как "не менее 8 бит" и значения "не менее чем от 0 до 255". Цитата Для обычного использования стоит использовать следующие: [u]int_leastN_t и [u]int_fastN_t (где N=8, 16, 32, 64). Всё это — типы, которые не уже указанного числа битов (то есть диапазон представления —2N—1+1...2N—1—1 для знаковых и 0...2N—1 для беззнаковых). При этом ..._least_t — самая компактная форма представления, а ..._fast_t — самая быстрая Тут же наоборот. Не ниже данного числа битов. Т.е. uint_fast8_t скорее всего окажется 32 битным, либо 8 бит с выравниванием до 10. Зависит от платформы. Подобное объявление просто позволяет не заморачиваться с различными особенностями платформ по части типов данных - компилятор подствит то, что нужно. Цитата rgba_pixel - а это зарезервированный тип или просто имя структуры? Имя. Цитата local img = ffi.new("rgba_pixel[?]", n)
Это в примере инициализация, я правильно понял, что n - это заранее объявленный размер массива? Это заранее НЕ объявленный размер массива. Этот разрмер передается при вызове функции, после чего массив создается. Заранее объявленный может быть только константой, т.е. по сути строкой либо переменной типа const. Цитата В моём случае x и y должны быть естественно типа word. 16 бит будет достаточно. Можно использовать определения выше: uint_fast16_t. Цитата И смогу я из функции вернуть такой массив в массив lua. Вы можете как минимум читать память этого массива, соответственно его вернуть. Насколько нужно его возвращать вызывает некоторые вопросы. Ведь можно все вычисления произвести прям там, что будет явно быстрее, а результат уже можно и вернуть. Цитата _,_,r1,r2=usl:find Можно вместо find использовать match. Разница только в том, что match не вернет позиции найденных вхождений. Т.е. то, что вы отправили в мусор (_,_,) даже создаваться не будет. Цитата if r1==nil then r1,r2=0,255 else if r2==nil then r2=r1 end end вместо else if можно использовать elseif (слитно). Спец оператор, вроде как от этого будет чуть быстрее. Цитата b=rmem("unsigned char*", ind)[0] g=rmem("unsigned char*", ind+1)[0] r=rmem("unsigned char*", ind+2)[0] if r>=r1 and r<=r2 and g>=g1 and g<=g2 and b>=b1 and b<=b2 and r-g>=RG1 and r-g<=RG2 and r-b>=RB1 and r-b<=RB2 and g-b>=GB1 and g-b<=GB2 then Возможно узкое место. При вызове rmem вы считываете char(8 бит) и сохраняете, как double (64 бита с плавающей точкой). Такое преобразование точно тормозит процесс. Тут имеет смысл проэкспериментировать либо с созданием функции: Код local function b() -- аналогично для других каналов return rmem("unsigned char*", ind)[0] end Сам факт вызова функции теоретически может дать просадку по скорости - надо тестить. Так же напрямую читать память прямо в условии. Это ухудшит читаемость, но, при условии грамотной реализации внутри lua - это будет самый быстрый вариант. Особое внимение при этом нужно уделить r1, r2 и прочим созданным переменным, которые используются в условии. Они являются типом double. Т.е. даже если мы избежим преобразования наших цветов в конструкции: b=rmem("unsigned char*", ind)[0] то они неизбежно будут преобразованы при сравнении, т.к. остальные переменные другого типа. Чтобы этого избежать нужно создать небольшую структурку, скорее всего такую же 8 битную(можно потестить разные варианты, т.к. производительность может изменится). Цитата ("R%((%d+)%-*(%d*)") Про регэкспы я уже писал - тут они вряд ли нужны, а они всегда скоростью не блещут. Проще задавать сразу таблицей, а не строкой.
--------------------
Скрипты UOPilot под заказ. Консультации по UOpilot 15$/час. Услуги Lua разработчика (не пилот, проекты, постоянка) Disсоrd: Kov____
|
|
|
|
sutra |
17.11.2018, 21:18
|
      
Adept
Сообщений: 923
Регистрация: 10.8.2018 Группа: Пользователи Наличность: 0
Пользователь №: 19.007

|
Цитата Сам факт вызова функции теоретически может дать просадку по скорости Вот вот, упредил мой вопрос. Насколько я помню, уж не знаю как комилируется в lua, вызов любой функции задействует стек, а это тоже время. А присваивание, даже разных типов, наверняка выполняется на самом низком уровне. Цитата Спец оператор, вроде как от этого будет чуть быстрее Опять же по логике, насколько я понимаю, компиляция тем и отличается от интерпретации, что автоматом оптимизирует код и любой if , else в результате просто выполнит свой джамп на нужный адрес. Но я обязательно потестирую все варианты, пёс его знает "современных" программистов, за ними нужен глаз, да глаз. Иногда, на первый взгляд безобидная вещь вызывает жуткие тормоза, а иногда и наоборот, вроде громоздкая вещь, а выполняется на ура. Цитата Проще задавать сразу таблицей, а не строкой Да что-то меня эти таблицы пугают своей громоздкостью и я вообще плохо понимаю их, как-то вот нет интуитивного понятия как они работают. Складывается ощущение что из таблиц в lua сделали одну большую огромную свалку (типа универсальность применения) и интуиция подсказывает мне, что выигрыша по скорости не будет. Да и не понимаю я пока как реализовать эту мысль на практике.
|
|
|
|
sutra |
17.11.2018, 21:40
|
      
Adept
Сообщений: 923
Регистрация: 10.8.2018 Группа: Пользователи Наличность: 0
Пользователь №: 19.007

|
Цитата arr[k]={j, i, r, g, b} Спасибо, sirus, не додумал, прирост производительности почти в 2 раза, точнее 1,8 раза.
|
|
|
|
DarkMaster |
17.11.2018, 21:42
|
          
Модератор UOPilot
Сообщений: 9.764
Регистрация: 2.12.2008 Группа: Супермодераторы Наличность: 29941
Пользователь №: 11.279

|
Цитата Насколько я помню, уж не знаю как комилируется в lua Конкретно в нашем случае (мы не на оригинальном lua, а на luajit) компиляция тут динамическая и как оно себя поведет предсказать не могу даже плюс минус километр, но выигрыш относительно оригинального lua огромен. Цитата вызов любой функции задействует стек, а это тоже время. Да, но при этом мы неизбежно вызываем функцию rmem, и едва ли она стек минует. Скорее всего тут вопрос в первую очередь стоит в том, развернет ли компилятор: Код local function rmem() ... end local function g() rmem(params) end a = g() В чистый вызов rmem минуя вызов g(). Тут у меня знаний и практики нет. Бесполезные пустые ифы и присвоения скипает на ура, а что с функциями будет я хз. Цитата компиляция тем и отличается от интерпретации, что автоматом оптимизирует код и любой if , else в результате просто выполнит свой джамп на нужный адрес. Тут компиляция динамическая, т.е. программа во время выполнения перекомпилируется при необходимости оптимизировать что-нибудь. Цитата Складывается ощущение что из таблиц в lua сделали одну большую огромную свалку (типа универсальность применения) В луа все является элементом таблицы. Вообще все. Цитата и интуиция подсказывает мне, что выигрыша по скорости не будет. Будет 100%. Вопрос в том на сколько этот выигрыш будет существенным. Цитата Да и не понимаю я пока как реализовать эту мысль на практике. Код local usl = {r1=10, g1=12} FindRGB(addr,len,scrX1,scrY1,fx1,fy1,fx2,fy2,usl,numf) r1 = usl.r1 or 0 -- если usl.r1 задан, то он останется, если не задан, то задаст 0. g1... b1... Тут прямо напрашивается, чтобы r1, g1, b1 и т.д. были сишными. Вот прям вот молит об этом. Сообщение отредактировал DarkMaster - 17.11.2018, 21:43
--------------------
Скрипты UOPilot под заказ. Консультации по UOpilot 15$/час. Услуги Lua разработчика (не пилот, проекты, постоянка) Disсоrd: Kov____
|
|
|
|
|
  |
10 чел. читают эту тему (гостей: 10, скрытых пользователей: 0)
Пользователей: 0
|
|