iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 26
0

還記得前幾天有談到的scope issue

當時一開始只是自己在寫loop時,發現全域變數在for-loop當中無法被改變,查看了官方文件之後,才知道原來是scope的問題。不過後來自己陸續在Julia的forum裡頭看到有人在抱怨討論這個issue,可見得這個新的規範大家還在適應中啊 XD。

話說回來

今天我在讀官方文件的Performance Tips時,又再度看到scope的正確使用是多麼地重要啊。

比如說,一個全域變數有沒有使用global開頭來宣告就會對程式的運行效率有很大的影響

x = rand(1000)
global y = rand(1000)

function sum_all()
	s = 0.0
	for i in x::Vector{Float64}
		s += i
	end
	return s
end

function sum_all_global()
	s = 0.0
	for i in y::Vector{Float64}
		s += i
	end
	return s
end

println("Test sum_all()")
@time sum_all()
println("Test sum_all_global()")
@time sum_all_global()

https://ithelp.ithome.com.tw/upload/images/20181027/201116880Pt23ZnY6P.png

執行這段程式碼,我們可以發現第一個版本(沒有使用global宣告)所需執行時間稍微長一些,但所花費的記憶體開銷卻大的多。所以官方文件基本上是建議大家盡量避免使用全域變數,或是真的要用的話就把這些全域變數用常數來宣告或當成參數傳給那些函數,像這樣:

function sum_all_with_para(x::Vector{Float64})
	s = 0.0
	for i in x
		s += i
	end
	return s
end

function sum_all_global_with_para(y::Vector{Float64})
	s = 0.0
	for i in y
		s += i
	end
	return s
end

https://ithelp.ithome.com.tw/upload/images/20181027/201116888xR9TZEKIQ.png

很明顯的,改成第二種版本後,記憶體的開銷馬上就降低成與加了global的版本一樣了。但還是很奇怪,怎麼一個簡單的for-loop會需要allocate這麼多次的記憶體呢? 官方文件說是因為我們在global scope裡頭用到@time這個macro,將它放到一個function當中就不會了,所以我再將程式改成這樣:

time_sum_all(x) = @time sum_all_with_para(x)
time_sum_all_global(x) = @time sum_all_global_with_para(x)

println("Test time_sum_all_with_para(x)")
time_sum_all(x)
println("Test time_sum_all_global_with_para(x)")

https://ithelp.ithome.com.tw/upload/images/20181027/20111688iqir7uxHzg.png

這才叫Julia要飛起來了啊

關於怎麼提昇Julia performance的方式,官方文件另外給出了一些建議

  • Avoid containers with abstract type parameters
  • Avoid fields with abstract containers
  • Annotate values taken from untyped locations
  • Declare types of keyword arguments
  • Break functions into multiple definitions (這也是阿杜提過的:善用multiple dispatch)
  • Write "type-stable" functions
  • Avoid changing the type of a variable
  • Separate kernel functions (aka, function barriers)
  • Types with values-as-parameters
    ..... 等

有興趣的朋友可以自行上去看看。


上一篇
[Day 25] 在Nextflow底下用Julia如何?
下一篇
[Day 27] 不算初次接觸的Metaprogramming
系列文
When Bioinfo met Julia: Bioinformatician的30天Julia學習之路32

1 則留言

0
杜岳華
iT邦新手 5 級 ‧ 2018-10-27 22:24:43

對於第1段的程式,比較好的用法應該是

x = rand(1000)

function sum_all()
	s = 0.0
	for i in x
		s += i
	end
	return s
end

function sum_all_global()
	s = 0.0
	global x
	for i in x
		s += i
	end
	return s
end

println("Test sum_all(): ", @time sum_all())
println("Test sum_all_global(): ", @time sum_all_global())

哇~ 原來可以這樣寫

應該是說,global 是用來標註這個變數是全域變數來的還是區域變數來的。

我要留言

立即登入留言