2016-11-14 4 views
2

Я пытаюсь использовать lua для прототипа параллельного алгоритма. С этим я хочу написать код в чистом Lua, выполнить тесты на нем, отладить его и т. Д. Тогда, когда я уверен, что он работает, я могу перевести его в настоящую многопоточную библиотеку или даже на другой язык (например, OpenCL kenel). Очевидно, что меня не интересует производительность кода прототипа.Имитировать параллелизм в Lua

Я думал использовать сопрограмму, которая дает в каждой строке, с некоторым шаблоном, чтобы случайным образом выбрать следующую «нить» для запуска. Например:

local function parallel_simulation(...) 

    local function_list = {...} 
    local coroutine_list = {} 
    local thread_number = #function_list 
    for i = 1, thread_number do 
    coroutine_list[i] = coroutine.create(function_list[i]) 
    end 

    while 0 < thread_number do 

    local current = math.random(1, thread_number) 
    local worker = coroutine_list[current] 

    coroutine.resume(worker) 

    if 'dead' == coroutine.status(worker) then 
     thread_number = thread_number - 1 
     table.remove(coroutine_list, current) 
    end 
    end 
end 

---------------------------------------------------------- 
-- Usage example 

local Y = coroutine.yield 
local max = 3 
local counter = 0 
local retry = 99 

local function increment() 
    Y() local c = counter 
    Y() while max > c do 
    Y() c = counter 
    Y() c = c + 1 
    Y() counter = c 
    Y() end 
end 

for i=1,retry do 
    counter = 0 
    parallel_simulation(increment, increment) 
    if max ~= counter then 
    print('Test SUCCESS ! A non-thread-safe algorithm was identified .', i, counter) 
    return 
    end 
end 

error('Test FAIL ! The non-thread-safe algorithm was not identified .') 

Это всего лишь идея, любое решение, включающее чистую Lua, приветствуется! Что делает меня очень неудобным с этим решением, все это Y(). Есть ли способ избежать их? (Debug.sethook не позволяет давать ...)

EDIT 1 - более значимый пример был предоставлен

EDIT 2 - Надеюсь, я clearified, что я пытаюсь сделать

+0

Я не понимаю, почему вы хотите передать управление после каждой строки. – warspyking

+1

При параллельном выполнении вы точно не знаете порядок выполнения команды, поэтому я хочу, чтобы мой код вел себя одинаково. Например, я хочу симулировать одновременную запись значения, чтобы определить необходимость мьютекса. Очевидно, что я могу поставить доход только на критической строке, но все дело в том, что, вероятно, я не знаю, что является критическим кодом. Предположим, что следующий шаг должен состоять в том, чтобы уступить после каждого кода команды VM (частичного теста). – mimmo

+0

Я не понимаю, почему это полезно, когда можно, скажем, просто сделать функцию 'sleep', которая будет так долго ждать, пока другая задача не будет спящей, и т.д. – warspyking

ответ

0

простой альтернативой поставив Y() перед каждой строки использовать gsub и load:

Y = coroutine.yield 
max = 3 
counter = 0 

code = [[ 
function increment() 
    local c = counter 
    while max > c do 
    c = counter 
    c = c + 1 
    counter = c 
    end 
end]] 
code = code:gsub("\n ", "\n Y() ") -- replace two spaces in find/replace with whatever tab character(s) you use 
assert(load(code))() 

local retry = 99 
-- rest of code here 

(используйте load или loadstring в зависимости от вашей версии Lua) Обратите внимание, что объявления переменных Y/max/counter должны быть глобальными, иначе загруженная функция не будет иметь к ним доступа. Аналогично, функция в code должна быть глобальной, иначе increment не будет существовать вне загруженного кода.

Такое решение предполагает, что все инструкции на каждой линии, конечно, являются атомными/потокобезопасными.

Улучшение, которое я бы рекомендовал сделать до parallel_simulation, заключается в том, чтобы добавить способ изменения способа выбора следующей нити. ex, возможно, ошибка будет обнаружена только в том случае, если один из потоков находится на ранней стадии исполнения, а другой уже почти выполнен - ​​хотя это состояние теоретически может быть достигнуто посредством достаточных случайных испытаний, имеющих аргумент, который позволяет вам регулировать, какие потоки больше вероятно, будет выбран следующим (например, с использованием весов), что должно сделать его гораздо более вероятным.

Смежные вопросы