首页 > 解决方案 > Julia 中的反向量化数组操作

问题描述

这个问题是我之前关于在 Python 中优化数组计算的问题之一的扩展。我给定问题的答案是通过@tomjn 给出的

tot_list = np.where((X == 1) | (Y == 1) | (Z == 1),np.random.random(),1).sum(axis=1)

现在,我想用 Julia 写这个。上面可以很容易地翻译为

tot_list = ifelse.((X.==1).|(Y.==1).|(Z.==1),rand(Float64),1)

请注意,X、Y 和 Z 是逻辑矩阵。当我在 Julia 中运行我的代码时,上述工作正常。但是,它非常缓慢。我正在尝试对上述内容进行去矢量化,我得到了

tot_list = similar(X)
for j in 1:length(tot_list)
    tot_list[j] = ifelse((X[j]==1)|(Y[j]==1)|(Z[j]==1),rand(Float64),1)
end

但是,生成的代码实际上不会产生与矢量化、低效版本相同的结果。我无法举一个例子,因为差异仅在非常大的输入时才明显,但我很肯定上面编写的 Julia 代码的两个部分之间存在很大差异。我究竟做错了什么?两个tot_lists不应该相同吗?

编辑:差异可能是由于我在执行此计算尝试进行的计算。在运行上述内容之前,我定义

variable_tot = zeros(Float64,1,8*N_state)

在我运行上面给出的 tot_list 计算之后,我运行

variable_tot=variable_tot+reshape(tot_list,:,length(tot_list))

这和我的问题有关系吗?

标签: pythonarrayslogicjuliavectorization

解决方案


也许试试这个代码:

((x) -> x ? rand() : 1.0).(X .| Y .| Z)

请注意,对于 Julia 函数而言,类型稳定对于性能至关重要。因为rand()is 返回Float64替代1值也需要是Float64- 并且因此1.0被使用而不是1.

性能测试 - 我的机器上 1'000'000 个元素矩阵需要 5 毫秒:

X = rand(Bool, 1000, 1000)
Y = rand(Bool, 1000, 1000)
Z = rand(Bool, 1000, 1000)

julia> using BenchmarkTools

julia> @btime ((x) -> x ? rand() : 1.0).($X .| $Y .| $Z)
  5.615 ms (2 allocations: 7.63 MiB)

推荐阅读