dll против Луа. Странности

Страницы: 1
RSS
dll против Луа. Странности
 
Вот функция на Си++ внутри dll. Она принимает таблицу и выдаёт обратно в Луа сумму элементов этой таблицы.
Код
static int forLua_SumArray(lua_State* L) {
   // Get the length of the table (same as # operator in Lua)
   int n = lua_objlen(L, 1);
   double sum = 0.0;
   // For each index from 1 to n, get the table value as a number and add to sum
   for (int i = 1; i <= n; ++i) {
      lua_rawgeti(L, 1, i);
      sum += lua_tonumber(L, -1);
      lua_pop(L, 1);
   }

   lua_pushnumber(L, sum);
   return 1;
}
Я ожидаю, что чем больше элементов будет в таблице, тем сильнее dll должна опережать аналогичные подсчёты в Луа.
Написал код для сравнения скорости.
Код
iterations=1000000
function main ()
   t={}
   for i=1,20 do--вставляем в таблицу 20 элементов
      table.insert(t,i)
   end
--гоняем цикл миллион раз
   start=os.clock()
   for i=1,iterations do
      s=runfast.SumArray(t)
   end
   finish_dll=os.clock()-start
   mm("dll:"..finish_dll)
--гоняем цикл миллион раз
   start=os.clock()
   for i=1,iterations do
      s=sum(t)
   end
   finish_lua=os.clock()-start
   mm("Lua:"..finish_lua)
   mm("Lua slower:"..math_round((finish_lua/finish_dll),1))
end

Луа медленнее в 2,4 раза. Я мучаюсь с Си ради роста скорости в 100 раз, ну да ладно. В 2,5 раза тоже кое-что. Сказываются транспортные издержки при перекидывании данных между Си и Луа.
************************
А теперь удивительное для меня. Заполняю таблицу 40 элементами.
Код
        t={}
   for i=1,40 do
      table.insert(t,i)
   end
Значит внутри Си++ будет производиться в 2 раза больше операций и она сможет лучше проявить своё преимущество в скорости по сравнению с Луа.
Но нет: при 40 элементах в таблице преимущество Си в скорости такое же.



Почему?
Я думал, что чем больше таблица, тем быстрее будет работать вариант кода с dll.
Объясните пожалуйста.
 
На всякий случай код функции sum, которая считает сумму элементов на Луа:
Код
function sum(t)
    local sum = 0
    for k,v in pairs(t) do
        sum = sum + v
    end
    return sum
end
 
Ну какие странности!?! С луа Вы почему то используете медленный for pairs, а в С++ быстрый for...

Попробуйте такую формулу для lua
Код
function sum(t)
    local sum = 0
    for x=1, #t do
        sum = sum + t[x]
    end
    return sum
end
P.S. Народ тут в поисках скорости в многопоточности и dll на плюсах совсем не видит, что миллион раз сладывает одно и тоже. Понимаю,что код во втором листинге делает это в качестве теста. Но посмотрите внимательно на свой "рабочий", нет ли там того же самого
 
Алексей Ч,
спасибо. Я не знал, что предложенный вами вариант будет быстрее. Обязательно начну использовать.
---
Но ваш комментарий о другом. Я про другое спросил. Почему dll не даёт преимущества в скорости на больших таблицах? Почему при обсчёте таблицы с 20 полями и таблицы с 40 полями разница в производительности одинаковая?  
 
Отвечу вопросом на вопрос. А почему Вы решили, что dll должно давать преимущество в скорости? "Общеизвестный факт" при проверке оказывается мифом.
 
Алексей Ч,
в предложенном вами варианте Луа равна по скорости dll на Си
Код
function sum_new(t)--функция Алексея Ч.
    local sum = 0
    for x=1, #t do
        sum = sum + t[x]
    end
    return sum
end
iterations=1000000
function main ()
   t={}
   for i=1,20 do
      table.insert(t,i)
   end
   start=os.clock()
   for i=1,iterations do
      s=runfast.SumArray(t)--функция из dll
   end
   finish_dll=os.clock()-start
   mm("dll:"..finish_dll)
   start=os.clock()
   for i=1,iterations do
      s=sum(t)--старая функция на Луа с for... pairs
   end
   finish_lua=os.clock()-start
   mm("Lua:"..finish_lua)   
   
   start=os.clock()
   for i=1,iterations do
      s=sum_new(t)--новая функция без pairs
   end
   finish_lua_new=os.clock()-start   
   mm("Lua new:"..finish_lua_new)
   mm("Lua old slower:"..math_round((finish_lua/finish_dll),1))
   mm("Lua new slower:"..math_round((finish_lua_new/finish_dll),1))   
end

 
Цитата
Let_it_go написал:
Вот функция на Си++ внутри dll. Она принимает таблицу и выдаёт обратно в Луа сумму элементов этой таблицы
Код
static int forLua_SumArray(lua_State* L) {
   // Get the length of the table (same as # operator in Lua)
   int n = lua_objlen(L, 1);
   double sum = 0.0;
   // For each index from 1 to n, get the table value as a number and add to sum
   for (int i = 1; i <= n; ++i) {
      lua_rawgeti(L, 1, i);
      sum += lua_tonumber(L, -1);
      lua_pop(L, 1);
   }

   lua_pushnumber(L, sum);
   return 1;
}
Я ожидаю, что чем больше элементов будет в таблице, тем сильнее dll должна опережать аналогичные подсчёты в Луа.
Вот такого плана код на С++. Здесь каждая содержательная строчка производит ту или иную манипуляцию со стеком Lua. То есть, в моем представлении, такой код фактически будет исполняться на том же самом интерпретаторе Lua как если бы он был написан непосредственно на Lua. И его быстродействие должно всегда оказываться по порядку величины сравнимым с Lua. Если он вообще на сколько-то быстрее уже хорошо.
Я прав? (в луа мало что понимаю поэтому спрашиваю)
 
Еще вопрос вдогонку, допустим про таблицу Lua заранее известно что она представляет из себя аналог Сишного массива базового типа. В примере этой конкретно темы фактически int Array[20]. Так вот как ее бычтрее всего закопировать в Сишный массив чтобы дальше с ним уже работать традиционным образом?
Получать каждый отдельный элемент вызывая в цикле
Код
lua_rawgeti(L, 1, i);       
sum += lua_tonumber(L, -1);       
lua_pop(L, 1);
выглядит откровенно расточительно. Какие-то более эффективные способы есть? Сам не нашел пока...
 
1. Вы правы.

2. При Ваших допущениях.
А зачем Вам копировать в Сишный массив? Не возникало мысли работать с данными прямо по месту их нахождения?
Есть, правда, некоторые трудности и даже опасности. Как минимум придется разобраться с устройством памяти в LUA, с ее динамикой и инфрастуктурой.
Но оно стоит того. На моих таблицах и алгоритмах заработало примерно в 30 раз быстрее. Для меня это было жизненно необходимо.
.

 
 
Цитата
Борис Гудылин написал:
А зачем Вам копировать в Сишный массив? Не возникало мысли работать с данными прямо по месту их нахождения?Есть, правда, некоторые трудности и даже опасности. Как минимум придется разобраться с устройством памяти в LUA, с ее динамикой и инфрастуктурой.Но оно стоит того. На моих таблицах и алгоритмах заработало примерно в 30 раз быстрее. Для меня это было жизненно необходимо.
1. Неудачно выразился, в рамках примера из этой темы разумеется ничего никуда копировать не надо. Надо именно найти прямое местонахождение данных для быстрейшего к ним доступа. В других каких-то случаях наверняка придется копировать для дальнейшей обработки / изучения и тд, но абсолютно согласен с тем что все равно первоочередная задача будет получить для начала прямой доступ к этим данным.
2. Мысль такая после обдумывания пришла. Как получить указатель на начало этих данных из документации накурил. Ничего кроме этого полезного там не нашлось, видимо далее дорога купить исходники. Развлекаюсь пока что чтением файла lobject.h.
В 30 раз быстрее даже больше чем я думал, есть за что побороться ))
 
Цитата
BlackBoar написал:
видимо далее дорога купить исходники
Ачипятка, имелось в виду "курить исходники"

И Борис Гудылин, благодарю за коммент, подтвердили ход моих мыслей :)
Страницы: 1
Читают тему
Наверх