Ruby Rake创建使用多任务的规则
如果我创建一个简单的规则,比如Ruby Rake创建使用多任务的规则,ruby,parallel-processing,rake,Ruby,Parallel Processing,Rake,如果我创建一个简单的规则,比如 rule '.o' => ['.c'] do |t| sh "cc #{t.source} -c -o #{t.name}" end 我怎样才能告诉Rake我希望自动生成的任务是可并行的呢?问题不是很清楚,但Rake::MultiTask不是你想要的吗 我自己也没用过,但医生建议: multitask :copy_files => [:copy_src, :copy_doc, :copy_bin] do puts "All Copies C
rule '.o' => ['.c'] do |t|
sh "cc #{t.source} -c -o #{t.name}"
end
我怎样才能告诉Rake我希望自动生成的任务是可并行的呢?问题不是很清楚,但Rake::MultiTask不是你想要的吗 我自己也没用过,但医生建议:
multitask :copy_files => [:copy_src, :copy_doc, :copy_bin] do
puts "All Copies Complete"
end
DSL中规则
的定义见lib/rake/DSL_definitions.rb
(在rake 10.1.1中):
不过,对当前代码的粗略扫描不会为DSL中的
规则
构造生成任何内置内容。如果有帮助,可以在代码中搜索@rules
和规则。
在lib/rake/task\u manager.rb中生成一个有趣的调用,其形式为增强与匹配的\u规则()
,如Dennis rake所述,规则作为任务实现
因此,将任务转换为多任务的-m标志也将规则转换为“多规则”
require 'rake/clean'
rule '.ext2' => '.ext1' do |t|
sh "cp #{t.source} #{t.name}"
sleep(1)
end
def dependencies(input_file)
base, is, ext = input_file.split('.')
_from, _to = is.split('-')
files = []
Integer(_from).upto(Integer(_to)) do |i|
files << "#{base}_#{i}.#{ext}"
end
return files
end
rule ".ext2" => lambda { |i| dependencies(i) } do |t|
sh "touch #{t.source}"
end
task :make_files do |t|
1.upto(20) do |i|
sh "touch file_#{i}.ext1"
end
end
CLEAN = FileList['*.ext2']
我明白了
具有5个线程:
rake clean
time rake -m -j 5 file.1-20.ext2
我明白了
有20个线程:
rake clean
time rake -m -j 20 file.1-20.ext2
我明白了
我使用sleep(1)来模拟“work/io”,如果您的进程阻塞很多,或者您有很多内核,这可能对您有用:)
编辑:正如Shadow在评论中指出的,以下选项将“多任务”切换为始终打开
Rake.application.options.always_multitask = true
我已经为此挣扎了一段时间。问题是规则
不允许并行执行其依赖项,而多任务
既不允许基于regex或glob的匹配,也不允许lambda作为依赖项。后者只会让您不知道如何构建任务“#”(请参见--tasks)
我采用的模式是动态组装多任务。以下内容将匹配“stuff_to_do:12:455:3434”之类的内容,并并行执行任务“task_12”、“task_455”和“task_3434”:
rule /stuff_to_do:(:?[0-9]+)+/ => :environment do |t|
doer = Rake::MultiTask.new("stuff",Rake.application)
doer.enhance(t.name.split(':')[1..-1].map{|number| "task_#{number}"})
doer.invoke
end
end可并行化的意思是什么?通过使用Thread.new和“join”-据我所知,他希望为dir中的每个文件并行执行相同的代码。我想知道是否有一个内置原语来实现这一点,比如下面提到的多任务,但对于“规则”任务本质上,我想要的是多任务,但有“规则”任务。i、 e.如果你这样做:rule'.o'=>['.c']do | t |我希望所有的.c文件并行编译,而不是sequentially@alexspeller:我已经有一段时间没有深入研究过Rake的代码了,但如果我没记错的话,规则是执行常规指令集的任务的语法糖。如果您扫描DSL的源代码以查找
def rule
,您可能最终会找到所需的任务语法。如果是这样的话,那么复制它并用多任务替换任务就可以了。@alexspeller:所以…我深入研究了一下,事实上,rule
似乎只是使用enhance\u with\u matching\u rule()
扩展了一个任务。我已经更新了我的答案来强调这一点,我怀疑有可能创建或重写内置编译任务,使其跨多个线程运行。(我猜Rake的维护人员会很乐意将它合并到一起,如果它能工作,并且你能成功的话。)感谢大家的关注,我将从那开始进一步研究这个问题point@alexspeller-m将任务转换为多任务,因为规则是任务这也适用于规则,请参阅我的答案以获取一个示例:)非常好-但是有没有一种方法可以默认允许这种行为?我找到了一种方法,这是一个小技巧-但是如果您的Rake文件中有Rake.application.options.always\u multitask=true
,它将启用此选项。虽然这是不可靠的,因为它不允许命令行以这种方式重写它,但在这个应用程序中我并不担心这一点。
real 0m4.152s
user 0m0.122s
sys 0m0.071s
rake clean
time rake -m -j 20 file.1-20.ext2
real 0m1.167s
user 0m0.130s
sys 0m0.065s
Rake.application.options.always_multitask = true
rule /stuff_to_do:(:?[0-9]+)+/ => :environment do |t|
doer = Rake::MultiTask.new("stuff",Rake.application)
doer.enhance(t.name.split(':')[1..-1].map{|number| "task_#{number}"})
doer.invoke
end