我有这个代码:
# Grab Nutrients.csv from https://data.nal.usda.gov/dataset/usda-branded-food-products-database/resource/c929dc84-1516-4ac7-bbb8-c0c191ca8cec
my @nutrients = "/path/to/Nutrients.csv".IO.lines;
for @nutrients.race {
my @data = $_.split('","');
.say if @data[2] eq "Protein" and @data[4] > 70 and @data[5] ~~ /^g/;
};
Run Code Online (Sandbox Code Playgroud)
Nutrients.csv 是一个 174 MB 的文件,有很多行。每一行都完成了重要的事情,但没有数据依赖性。然而,这大约需要 54 秒,而非竞赛版本使用 43 秒,减少了 20%。知道为什么会这样吗?在这里完成的操作对于数据并行性来说是否仍然太少?我见过它只适用于非常繁重的操作,比如检查某些东西是否是素数。在那种情况下,是否应该为每条数据做多少工作才能使数据并行化值得呢?
假设“跑赢大盘”被定义为“使用更少的挂钟”:
简短的回答:当它发生时。
更长的答案:当批处理值的开销、分布在多个线程上并收集结果 + 工作所需的实际 CPU 除以线程数时,会导致更短的运行时间。
更长的答案:调度程序线程需要一些 CPU 来批量处理值并将工作移交给工作线程,然后处理其结果。只要该 CPU数量大于完成工作所需的 CPU 数量,您将只使用一个线程(因为在调度程序线程准备好调度时,唯一的工作线程已准备好接收更多工作) . 这意味着你让事情变得更糟,因为实际工作现在仍然由一个线程完成,但是你增加了很多开销和延迟。
因此,请确保工作线程需要执行的工作量足够大,以便调度程序线程需要为下一项工作启动另一个线程。这可以通过增加批量大小来完成。但是更大的批处理也意味着调度程序线程将需要更多的 CPU 来创建批处理。这反过来可以使工作线程准备好接收下一批,在这种情况下,您又回到了增加开销的情况。
仍然有计划使批处理大小自动适应工作线程需要完成的工作量。但不幸的是,这也将要求目前执行的相当广泛的改造hyper和race。所以不要指望很快就会出现这种情况,而且绝对不会在大调度器大修到来之前。
请看一看:
Raku .hyper() 和 .race() 示例不起作用
您示例中的语法应该是:
my @nutrients = "/path/to/Nutrients.csv".IO.lines;
race for @nutrients.race(batch => 1, degree => 2)
{
my @data = $_.split('","');
.say if @data[2] eq "Protein" and @data[4] > 70 and @data[5] ~~ /^g/;
}
Run Code Online (Sandbox Code Playgroud)
“for”前面的“race”有所不同。
| 归档时间: |
|
| 查看次数: |
153 次 |
| 最近记录: |