Julia 1.5.2 性能问题
Julia 1.5.2 Performance Questions
我目前正在尝试实现元启发式(遗传)算法。在这次冒险中,我还想尝试创建一些快速高效的代码。但是,我在创建高效编码方面的经验并不是很好。因此,我想知道是否有人可以提供一些“快速提示”来提高我的代码效率。我已经为我的代码创建了一个小的功能示例,其中包含代码将包含的大部分元素,这些元素与预分配数组、自定义可变结构、随机数、推入数组等有关。
我已经尝试探索的选项是关于包“StaticArrays”的选项。然而,我的许多数组必须是可变的(因此我们需要 MArrays)并且其中许多将变得非常大 > 100。StaticArrays 的文档指定 StaticArrays 包的大小必须保持较小以保持高效。
根据文档,关于 rand(),Julia 1.5.2 应该是线程安全的。因此,我尝试在我的函数中使用多线程 for 循环,以使它们 运行 更快。这会导致性能略有提高。
但是,如果人们能找到一种更有效的方法来分配数组或将 SpotPrices 推入数组,将不胜感激!也非常欢迎任何其他性能提示!
# Packages
clearconsole()
using DataFrames
using Random
using BenchmarkTools
Random.seed!(42)
df = DataFrame( SpotPrice = convert(Array{Float64}, rand(-266:500,8832)),
month = repeat([1,2,3,4,5,6,7,8,9,10,11,12]; outer = 736),
hour = repeat([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]; outer = 368))
# Data structure for the prices per hour
mutable struct SpotPrices
hour :: Array{Float64,1}
end
# Fill-out data structure
function setup_prices(df::DataFrame)
prices = []
for i in 1:length(unique(df[:,3]))
push!(prices, SpotPrices(filter(row -> row.hour == i, df).SpotPrice))
end
return prices
end
prices = setup_prices(df)
# Sampler function
function MC_Sampler(prices::Vector{Any}, sample_size::Int64)
# Picking the samples
tmp = zeros(sample_size, 24)
# Sampling per hour
for i in 1:24
tmp[:,i] = rand(prices[i].hour, sample_size)
end
return tmp
end
samples = MC_Sampler(prices, 100)
@btime setup_prices(df)
@btime MC_Sampler(prices,100)
function setup_prices_par(df::DataFrame)
prices = []
@sync Threads.@threads for i in 1:length(unique(df[:,3]))
push!(prices, SpotPrices(filter(row -> row.hour == i, df).SpotPrice))
end
return prices
end
# Sampler function
function MC_Sampler_par(prices::Vector{Any}, sample_size::Int64)
# Picking the samples
tmp = zeros(sample_size, 24)
# Sampling per hour
@sync Threads.@threads for i in 1:24
tmp[:,i] = rand(prices[i].hour, sample_size)
end
return tmp
end
@btime setup_prices_par(df)
@btime MC_Sampler_par(prices,100)
看看仔细阅读https://docs.julialang.org/en/v1/manual/performance-tips/
基本清理开始于:
- 你的
SpotPrices
struct
不需要对我可变。无论如何,因为只有一个字段,您可以将其定义为 SpotPrices=Vector{Float64}
- 您不想要无类型的容器 - 而不是
prices = []
做 prices = Float64[]
- 使用
DataFrames.groupby
比查找唯一元素并按它们过滤要快得多
- 如果你不需要初始化而不是不初始化
Vector{Float64}(undef, sample_size)
比 zeros(sample_size, 24)
快得多
- 多线程循环前不需要同步
@sync
- 创建随机状态 - 每个线程一个单独的状态,并在调用
rand
函数时使用它们
我目前正在尝试实现元启发式(遗传)算法。在这次冒险中,我还想尝试创建一些快速高效的代码。但是,我在创建高效编码方面的经验并不是很好。因此,我想知道是否有人可以提供一些“快速提示”来提高我的代码效率。我已经为我的代码创建了一个小的功能示例,其中包含代码将包含的大部分元素,这些元素与预分配数组、自定义可变结构、随机数、推入数组等有关。
我已经尝试探索的选项是关于包“StaticArrays”的选项。然而,我的许多数组必须是可变的(因此我们需要 MArrays)并且其中许多将变得非常大 > 100。StaticArrays 的文档指定 StaticArrays 包的大小必须保持较小以保持高效。
根据文档,关于 rand(),Julia 1.5.2 应该是线程安全的。因此,我尝试在我的函数中使用多线程 for 循环,以使它们 运行 更快。这会导致性能略有提高。
但是,如果人们能找到一种更有效的方法来分配数组或将 SpotPrices 推入数组,将不胜感激!也非常欢迎任何其他性能提示!
# Packages
clearconsole()
using DataFrames
using Random
using BenchmarkTools
Random.seed!(42)
df = DataFrame( SpotPrice = convert(Array{Float64}, rand(-266:500,8832)),
month = repeat([1,2,3,4,5,6,7,8,9,10,11,12]; outer = 736),
hour = repeat([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]; outer = 368))
# Data structure for the prices per hour
mutable struct SpotPrices
hour :: Array{Float64,1}
end
# Fill-out data structure
function setup_prices(df::DataFrame)
prices = []
for i in 1:length(unique(df[:,3]))
push!(prices, SpotPrices(filter(row -> row.hour == i, df).SpotPrice))
end
return prices
end
prices = setup_prices(df)
# Sampler function
function MC_Sampler(prices::Vector{Any}, sample_size::Int64)
# Picking the samples
tmp = zeros(sample_size, 24)
# Sampling per hour
for i in 1:24
tmp[:,i] = rand(prices[i].hour, sample_size)
end
return tmp
end
samples = MC_Sampler(prices, 100)
@btime setup_prices(df)
@btime MC_Sampler(prices,100)
function setup_prices_par(df::DataFrame)
prices = []
@sync Threads.@threads for i in 1:length(unique(df[:,3]))
push!(prices, SpotPrices(filter(row -> row.hour == i, df).SpotPrice))
end
return prices
end
# Sampler function
function MC_Sampler_par(prices::Vector{Any}, sample_size::Int64)
# Picking the samples
tmp = zeros(sample_size, 24)
# Sampling per hour
@sync Threads.@threads for i in 1:24
tmp[:,i] = rand(prices[i].hour, sample_size)
end
return tmp
end
@btime setup_prices_par(df)
@btime MC_Sampler_par(prices,100)
看看仔细阅读https://docs.julialang.org/en/v1/manual/performance-tips/
基本清理开始于:
- 你的
SpotPrices
struct
不需要对我可变。无论如何,因为只有一个字段,您可以将其定义为SpotPrices=Vector{Float64}
- 您不想要无类型的容器 - 而不是
prices = []
做prices = Float64[]
- 使用
DataFrames.groupby
比查找唯一元素并按它们过滤要快得多 - 如果你不需要初始化而不是不初始化
Vector{Float64}(undef, sample_size)
比zeros(sample_size, 24)
快得多
- 多线程循环前不需要同步
@sync
- 创建随机状态 - 每个线程一个单独的状态,并在调用
rand
函数时使用它们