Каков наиболее эффективный способ передать некоторые постоянные аргументы функции в Julia? - PullRequest
0 голосов
/ 25 мая 2020

Предположим, у меня есть следующая функция

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 ] с мемоизацией и без:

Без:

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

1 Ответ

2 голосов
/ 25 мая 2020

Возможно, кеширование результата вашего звонка на do_some_intense_stuff(a) поможет, например, используя Memoize.jl .

...