Macros 朱莉娅:将包含关键字的代码注入到scipt中
我有一个包含for循环的函数。我想为该函数添加一个参数,让我选择使用Macros 朱莉娅:将包含关键字的代码注入到scipt中,macros,julia,keyword,Macros,Julia,Keyword,我有一个包含for循环的函数。我想为该函数添加一个参数,让我选择使用 线程。@i的线程在…中。 因此,我只需要在循环前面注入线程。@Threads。宏无法工作,因为它们无法处理关键字。 或者我可以有类似的东西 if parrallel inject("Threads.@threads for i in 1:n") else inject("for i in 1:n") end loop content.... end 我找不到任
线程。@i的线程在…
中。
因此,我只需要在循环前面注入线程。@Threads
。宏无法工作,因为它们无法处理关键字。
或者我可以有类似的东西
if parrallel
inject("Threads.@threads for i in 1:n")
else
inject("for i in 1:n")
end
loop content....
end
我找不到任何方法插入这样的代码。怎么办
当然,可以选择将整个循环放在一个函数中,然后在函数上使用包含for循环的if-else,但我更希望代码的其余部分保持原样。及时插入代码并不容易。编译器不知道该做什么,也不会进行任何优化,也不会安全。有关类似问题,请参见: 我可以通过为for循环编写一个单独的函数(在我看来是更简洁的方式),或者将for循环留在第一个函数中,然后将其加倍编写来编写代码 比如:
function forloopcontent()
println(Threads.threadid())
end
function f(parallel::Bool)
if parallel
Threads.@threads for i in 1:10
forloopcontent()
end
else for i in 1:10
forloopcontent()
end
end
end
否则,您还可以为并行版本编写另一个函数,为普通版本编写两个不同的方法。即:
function f(;parallel::Bool=false)
parallel ? (return par_f()) : (return f())
end
function f()
for i in 1:10
println(Threads.threadid())
end
end
function par_f()
Threads.@threads for i in 1:10
println(Threads.threadid())
end
end
对于并行版本,此版本可以称为f(;parallel=true)
,对于非并行版本,此版本可以称为f(;parallel=false)
当然,可以选择将整个循环放在一个函数中,并在函数上使用包含for循环的if-else,但我更喜欢代码的其余部分
请注意,高阶函数和语法糖类使此类解决方案相对简单,易于开发和阅读:
您可以开始定义两个抽象for循环的高阶函数
# This one is basically `Base.foreach`
function sequential_for(f, iterable)
for i in iterable
f(i)
end
end
# A thread-parallel version
function parallel_for(f, iterable)
Threads.@threads for i in iterable
f(i)
end
end
然后,您的函数可以动态决定要使用哪个版本的for循环:
function my_fun(n; parallel=false)
for_loop = parallel ? parallel_for : sequential_for
x = zeros(Int, n)
# The do syntax avoids having to either
# - define the loop body as a named function elsewhere, or
# - put an hard-to-read lambda directly as argument to `for_loop`
for_loop(1:n) do i
x[i] = Threads.threadid()
sleep(0.1) # Let's make sure we see the effect of parallelism :-)
end
return x
end
示例用法:
julia> @time my_fun(10)
1.025307 seconds (299 allocations: 17.109 KiB)
10-element Array{Int64,1}:
1
1
1
1
1
1
1
1
1
1
julia> @time my_fun(10, parallel=true)
0.235430 seconds (18.44 k allocations: 979.714 KiB)
10-element Array{Int64,1}:
1
1
2
2
3
4
5
6
7
8
及时注入代码听起来不是一种好的或简单的方法。这里有一个类似的问题:。我读到了这一点,但我认为提出的问题不适用,因为我希望在函数内而不是从函数外部执行。您希望像这样插入代码的原因是什么?在我看来,这是一种非常奇怪的编程方式。它无法正确编译,很难做到,也没有任何明显的优势。我错了吗?也许是不完整;)我确实认为这可能不是最优的,但基本上我只是在寻找一种尽可能多地保留代码的方法。