我要解析的本地计算机上有一个相对较大的文件(〜10 GB):对于其中包含字符串"bobby"
的每一行,我想将整行存储在数组。这是我最初的尝试:
function runner()
io = open("large_10gb_file.txt", "r")
data = []
for line in eachline(io)
if occursin("bobby", line)
push!(data, line)
end
end
close(io)
return data
end
这很好用。但是,我看到当我调用runner()
时,它使用一个CPU内核(利用率为100%);我在笔记本电脑上可以使用5个以上的CPU内核-如何修改代码才能做到这一点?实际上,这样做是否有意义,因为文件可能是IO绑定在我的NVMe SSD上,而不是CPU绑定了?
这是我最初的并行化尝试:
function runner()
io = open("large_10gb_file.txt", "r")
data = []
@distributed for line in eachline(io)
if occursin("bobby", line)
push!(data, line)
end
end
close(io)
return data
end
但是,上面的方法返回一个空(0元素)数组。因此,我添加了@sync
来同步线程并保证返回顺序:
function runner()
io = open("large_10gb_file.txt", "r")
data = []
@sync @distributed for line in eachline(io)
if occursin("bobby", line)
push!(data, line)
end
end
close(io)
return data
end
但是,这将返回错误:
ERROR: MethodError: no method matching length(::Base.EachLine{IOStream})
Closest candidates are:
length(::Core.SimpleVector) at essentials.jl:571
length(::Base.MethodList) at reflection.jl:728
length(::Core.MethodTable) at reflection.jl:802
...
(::getfield(Distributed, Symbol("##169#171")){getfield(Main, Symbol("##9#10")){Array{Any,1}},Base.EachLine{IOStream}})() at ./task.jl:244
Stacktrace:
[1] sync_end(::Array{Any,1}) at ./task.jl:226
[2] macro expansion at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.0/Distributed/src/macros.jl:337 [inlined]
[3] macro expansion at ./task.jl:244 [inlined]
[4] runner() at ./REPL[73]:4
[5] top-level scope at none:0
我不熟悉Julia(昨天才刚开始学习语法),但是似乎eachline
调用没有与length
匹配的方法,因此{{1 }}无法准确地划分不同工作人员之间的工作。
注意:在运行@distributed for
之前,我确实做了addprocs(4)
,之后@distributed for
开始返回procs()
。