multithreading - 存储多线程函数调用输出的最佳方式
问题描述
我有一个f()
返回 DataFrame 的函数,它的行数我事先不知道。我f()
在多线程上下文中调用。我正在存储这样的结果:
results = [DataFrame() for _ in 1:100]
Threads.@threads for hi in 1:100
results[hi] = f(df)
end
当我运行此代码时,内存使用量会爆炸,大概是因为results
当它获得 DataFrame 的大小时必须不断调整自身大小[编辑:这不是真的]。预分配结果数组以使内存不会爆炸的最佳方法是什么?
**** 使用 MWE 更新 ****
function func(df::DataFrame)
X = df[:time]
indices = findall(X .> 0)
end
# read in R data
rds = "blablab.rds"
objs = load(rds);
params = collect(0.5:0.005:0.7);
for i in 1:length(objs)
cols = [string(name) for name in names(objs.data[i]) if occursin("blabla",string(name))]
hypers = [(a,b) for a in cols, b in params]
results = [DataFrame() for _ in 1:length(hypers)]
# HERE IS WHERE THE MEMORY BLOWS UP
Threads.@threads for hi in 1:length(hypers)
name, val = hypers[hi]
results[hi] = func(objs.data[i])
end
end
df
为 0.7GB。当我运行这段代码时,我的内存使用量高达〜30GB!!!似乎只是访问df
里面的一列就是在func()
复制整个内容?
解决方案
请在下面找到相同代码的两个版本 - 单线程和多线程DataFrame
从函数返回的一组DataFrame
s生成一个f()
并具有随机长度。
using Random
using DataFrames
using BenchmarkTools
function f(rngs::Vector{Random.MersenneTwister}, offset)::DataFrame
t = Threads.threadid()
n = rand(rngs[t+offset], 1:20)
DataFrame(a=1:n,b=21:(20+n),t=t+offset)
end
function test_threads(rngs::Vector{Random.MersenneTwister})
res = DataFrame([Int,Int,Int],[:a,:b,:t],0)
lock = Threads.SpinLock()
Threads.@threads for i in 1:100
df = f(rngs,0)
Threads.lock(lock)
append!(res,df)
Threads.unlock(lock)
end
res
end
function test_normal(rngs::Vector{Random.MersenneTwister})
res = DataFrame([Int,Int,Int],[:a,:b,:t],0)
for i in 1:100
append!(res,f(rngs, i%2))
end
res
end
现在让我们进行测试:
julia> rngs = [Random.MersenneTwister(i) for i in 1:2];
julia> @btime test_normal($rngs);
891.306 μs (5983 allocations: 476.67 KiB)
rngs = [Random.MersenneTwister(i) for i in 1:Threads.nthreads()];
@btime test_threads($rngs);
674.559 μs (5549 allocations: 425.69 KiB)
推荐阅读
- flutter - 从 CheckboxListTile 中删除内部填充
- java - Project loom:是什么让使用虚拟线程时性能更好?
- javascript - 克隆 div 没有被删除,只是原来的
- flutter - 使用可注入 pub 包时未定义函数“$initGetIt”
- python - 重构 2 dicts 值比较
- javascript - 如何记录使用 Apollo Federation 和 Apollo Gateway 构建的 API 网关?
- python-3.x - 编写一个程序来识别给定的行是否/有注释
- java - 确保只有一个 obj 使用 2 个属性组合创建的 DDD 方法是什么
- azure - 我需要在 Azure 中创建一个临时密钥以在 Terraform 中使用
- python - Snowflake pandas pd_writer 用 NULL 写出表