2016-11-14 6 views
2

私はいくつかの並列アルゴリズムをプロトタイプ化するためにluaを使用しようとしています。これは私が純粋なLuaでコードを書いてテストを行い、それをデバッグすることなどを意味します。そして、それが動作すると確信したら、真のマルチスレッドライブラリ、あるいは別の言語(例えばOpenCL kenel )。明らかに私はプロトタイプコードの実行には何ら関心がありません。ルアでの並列処理をシミュレートします

私は、各行で得られるコルーチンを使用すると考えていましたが、実行する次の「スレッド」をランダムに選択する定型文があります。例:

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を提供した - うまくいけば、私は

+0

すべての行の後にコントロールを渡す理由がわかりません。 – warspyking

+1

並列実行では、命令の実行順序が正確ではないので、同じ方法でコードの振る舞いをしたいと思います。たとえば、mutexの必要性を突き止めるために並行値書き込みをシミュレートしたいとします。当然のことながら、歩留まりはクリティカルライン上にのみ置くことができますが、重要な点はおそらく私が知りません。次のステップは(テスト中のチャンクの)各VM命令コードの後に​​降伏することであるとしましょう。 – mimmo

+0

私はこれがなぜ簡単に言うことができるのか分かりません。なぜなら、スリープ状態になると、他のタスクがスリープ状態になるまで待つことを長時間待つ機能です。 – warspyking

答えて

0

簡単な代替にを達成しようとしています何clearified各行の前にY()を置くことはgsubloadを使用することです:

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 

(あなたのLuaのバージョンに応じて、loadloadstringを使用) 変数宣言Y/max/counterはグローバルでなければなりません。そうしないと、ロードされた関数はそれらにアクセスできなくなります。同様に、codeの関数はグローバルでなければなりません。そうしないと、incrementはロードされたコードの外には存在しません。

このような解決策は、もちろん、各行のすべての命令がアトミック/スレッドセーフであることを前提としています。

私はparallel_simulationにすることをお勧めします。次のスレッドの選択方法を変更する方法を追加することです。おそらく、スレッドの1つが早期に実行され、もう1つがほぼ完了した場合にのみエラーが表示されますが、理論的には十分なランダムトライアルで到達できますが、次に選択される可能性が高い(ウェイトを使用している)場合は、その可能性が高くなります。