2017-05-29 221 views
2

比方說,我有一個名爲三角函數,它返回兩個輸出:從映射函數返回多個值

function trig(x) 
    return(sin(x), cos(x)) 
end 

如果我想對很多值來評價制動,我可以使用地圖功能:

julia> out = map(trig, (0:(pi/12):(pi/2))) 

出是一個7元件陣列和中的每個元素,存在包含兩個元素的元組:

julia> out 
7-element Array{Tuple{Float64,Float64},1}: 
(0.0,1.0) 
(0.258819,0.965926) 
(0.5,0.866025) 
(0.707107,0.707107) 
(0.866025,0.5) 
(0.965926,0.258819) 
(1.0,6.12323e-17) 

我的曲estion是:什麼是解開我的正弦和餘弦的最好方法,以便我有兩個每個都有7個元素的數組?是否可以在不創建多餘元組數組的情況下廣播trig,而是直接創建兩個實際感興趣的數組?

暫時,我才能從出以填充我想要的陣列中提取值再次調用地圖,但我不認爲這是做到這一點的最好辦法:

sines = map(x->x[1], out) 
cosines = map(x->x[2], out) 

對於這個問題,假定trig是一個計算量很大的函數。所以,請不要給我一個要求trig多次評估的答案。

+0

我不認爲有什麼辦法可以在沒有重新分配的情況下做到這一點,因爲例如在內存中「0.0」和「0.258819」並不相鄰(「1.0」在兩者之間)。要看到這個,使用'reinterpret(Float64,out,(2,7))',它沒有開銷,但是請注意'sines'是輸出矩陣的第一行,'cosines'是第二行,並且由於數組是列主要的順序,因此將'sines'提取爲'Vector' *必須*觸發重新分配。換句話說,我懷疑'map'將會像解決這個問題一樣好... –

+1

或者,只需爲'AbstractVector'輸入大小寫的'trig'提供自己的方法定義,並將調用的輸出分配給問題中的trig方法明確地指向兩個向量。有可能是一個聰明的單線程來做到這一點,但我不能看到它從我的頭頂(我的版本將有一個預分配線和顯式循環) –

+1

也參見https://stackoverflow.com/q/44010033和https://stackoverflow.com/q/41183481/6172490。 – tim

回答

1

謝謝你提出這個問題之前,我在搜索中一定忽略了一個早期問題的答案。在今天之前,我從來沒有聽說過的getIndex的功能,但它似乎getindex是我想要的功能,前提是我向量化它通過把一個點在前面:

julia> @time sine_map = map(x->x[1], out) 
    0.051494 seconds (13.32 k allocations: 602.941 KB) 
7-element Array{Float64,1}: 
0.0 
0.258819 
0.5 
0.707107 
0.866025 
0.965926 
1.0 

julia> @time sine_geti = getindex.(out, 1) 
    0.029560 seconds (9.24 k allocations: 416.910 KB) 
7-element Array{Float64,1}: 
0.0 
0.258819 
0.5 
0.707107 
0.866025 
0.965926 
1.0 

julia> @time cosine_map = map(x->x[2], out) 
    0.037328 seconds (13.32 k allocations: 602.941 KB) 
7-element Array{Float64,1}: 
1.0 
0.965926 
0.866025 
0.707107 
0.5 
0.258819 
6.12323e-17 

julia> @time cosey_geti = getindex.(out, 2) 
    0.024785 seconds (9.24 k allocations: 416.910 KB) 
7-element Array{Float64,1}: 
1.0 
0.965926 
0.866025 
0.707107 
0.5 
0.258819 
6.12323e-17 

減少分配的數量由30%沒什麼可以打噴嚏的。謝謝。

我想我是安全的使這個更簡潔:

@time sines, cosines = map(x->getindex.(out, x), 1:2) 
    0.062047 seconds (20.81 k allocations: 956.831 KB) 
2-element Array{Array{Float64,1},1}: 
[0.0,0.258819,0.5,0.707107,0.866025,0.965926,1.0] 
[1.0,0.965926,0.866025,0.707107,0.5,0.258819,6.12323e-17] 

謝謝你科林牛逼鮑爾斯的暗示我可以定義三角函數的自定義方法。如果getindex無法提供我想要的效果,我肯定會考慮這樣做。

+0

嘗試'sines,餘弦=地圖(收集,拉鍊(出...))''也。雖然可能效率不高。 –

+1

請勿在全球範圍內進行基準測試。將代碼封裝在一個函數中,或者使用'BenchmarkTools'和'@btime getindex。($ out,1)'代替。 – tim