首页 > 解决方案 > 将一些常量参数传递给 Julia 中的函数的最有效方法是什么?

问题描述

假设我有以下功能

function foo(x::Float64, a::Float64)
    if do_some_intense_stuff(a)
        return bar(x)
    else
        return baz(x)
    end
end

让我们假设在运行时a将是一个常数。但x不会。我要跑foo()很多次,所以我希望它跑得越快越好,这意味着do_some_intense_stuff尽可能少地跑。因为是一个常数,所以在运行时我们知道语句应该采用a哪个分支。if

所以理想情况下,我会做以下事情:

foowrapper(x) = foo(x,a)
Y = [foowrapper(x) for x in lots_of_x]

它会比

Y = [foo(x,a) for x in lots_of_x]

但事实并非如此。我不会责怪编译器没有优化我的代码,因为我没有明确告诉它foo()只会用a. 但是我有什么好的方法可以做到这一点吗?

当然,我总是可以摆脱foo并只在全局范围内编写该if语句,但这似乎不优雅,因为程序的其余部分并不关心do_some_intense_stuff()

更新:

为了对下面建议的解决方案进行基准测试,我实现了如下功能。出于显而易见的原因,我还修改了 的声明以foo()生成a整数:

function bar(x::Float64)
    return 2 * x
    #println("Ran bar for value ",x)
end

function baz(x::Float64)
    return -2 * x
    #println("Ran baz for value ",x)
end

@memoize function do_some_intense_stuff(a::Int64)
 return isprime(a + 32614262352646106013967035018546810367130464316134634614)
end

并定义lots_of_x = 1.0:1.0:1000.0.

这是@benchmark Y = [foo(x,a) for x in lots_of_x ]使用和不使用 memoize 的输出:

没有:

BenchmarkTools.Trial:
  memory estimate:  109.50 KiB
  allocs estimate:  5001
  --------------
  minimum time:     6.858 ms (0.00% GC)
  median time:      6.924 ms (0.00% GC)
  mean time:        7.067 ms (0.77% GC)
  maximum time:     78.747 ms (49.00% GC)
  --------------
  samples:          707
  evals/sample:     1

和:

BenchmarkTools.Trial:
  memory estimate:  39.19 KiB
  allocs estimate:  2001
  --------------
  minimum time:     97.500 μs (0.00% GC)
  median time:      98.801 μs (0.00% GC)
  mean time:        108.897 μs (1.37% GC)
  maximum time:     2.099 ms (93.76% GC)
  --------------
  samples:          10000

标签: functionclosuresjulia

解决方案


也许缓存您调用的结果do_some_intense_stuff(a)会有所帮助,例如使用Memoize.jl


推荐阅读