我正在尝试使用lua来构建一些并行算法的原型。我的意思是用纯Lua编写代码,对它进行测试,调试,等等。然后,当我确信它可以工作时,我可以把它翻译成一个真正的多线程库,甚至是另一种语言(例如OpenCL内核)。显然,我并不关心原型代码的性能。
我想使用一个在每一行产生的协程,用一些样板来随机选择下一个要运行的“线程”。例如:
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不允许让步...)
编辑1-提供了更有意义的示例
编辑2-希望我弄清楚了我想要实现的目标
发布于 2017-09-08 14:33:43
将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(根据您的Lua版本使用load或loadstring )请注意,变量声明Y/max/counter必须是全局的,否则加载的函数将无法访问它们。类似地,code中的函数必须是全局的,否则increment将不会存在于加载的代码之外。
当然,这样的解决方案假设每行上的所有指令都是原子/线程安全的。
我建议对parallel_simulation进行的一项改进是添加一些方法来更改如何选择下一个线程。例如,也许只有当一个线程在早期执行而另一个线程几乎完成时,错误才会显示出来-尽管这种状态理论上可以通过足够的随机试验来达到,但有一个参数可以让你调整下一个线程更有可能被选择(例如使用权重),这应该会使它更有可能。
https://stackoverflow.com/questions/40593848
复制相似问题