2016-04-03 15 views
6

Mam tablicę 2D, które chcę zmodyfikować, aby podsumować dany element w wierszu z wszystkimi elementami przed nim, więc na przykład, jeśli mam tablicę:Wydajny sposób na sumowanie tablicę liczb całkowitych w Julia

[1 2; 3 6; 4 7; 4 8] 

Chcę być w stanie przekształcić go

[1 2; 4 8; 8 15; 12 23] 

mogę zrobić za pomocą poniższego fragmentu kodu w Julia:

for i in 1:10, 
    for k in 2:size(d,1), 
      d([k,i] += d[k-1,i)]; 
    end 
end 

Zakładam jednak, że musi być na to skuteczniejszy sposób?

+3

Jeśli przez "efektywny" rozumie się "wydajność", o ile umieścisz tę pętlę w funkcji, będzie ona zasadniczo tak samo wydajna jak funkcja biblioteczna - funkcja biblioteczna różni się tylko ogólnością, umożliwiając wybierz dowolny wymiar. Jedną z przyjemności korzystania z Julii jest to, że nie musisz polegać na funkcjach bibliotecznych na wszystko. – tholy

Odpowiedz

16

Tak, jest: cumSum

julia> d = [1 2; 3 6; 4 7; 4 8] 
4x2 Array{Int64,2}: 
1 2 
3 6 
4 7 
4 8 

julia> cumsum(d) 
4x2 Array{Int64,2}: 
    1 2 
    4 8 
    8 15 
12 23 
4

Zgodnie użytkownika @ THOLY komentarz, niesamowite rzeczą jest to, że Julia wbudowane funkcje nie są wyjątkowe i nie są magicznie szybciej niż zdefiniowane przez użytkownika te. Obie są szybkie. I zmodyfikowane swoją funkcję i mam to wykonać prawie taka sama jak wbudowanych cumsum:

function testA!(arr) 
    @inbounds for i in 1:size(arr, 2) 
     tmp = arr[1, i] 
     for k in 2:size(arr,1) 
      tmp += arr[k, i] 
      arr[k,i] = tmp 
     end 
    end 
    arr 
end 

function testB!(arr) 
    cumsum!(arr, arr) 
end 

budowałem tablic testowych:

arr = rand(1:100, 10^5, 10^2) 
arr2 = copy(arr) 

i mam następujące czasy:

@time testA!(arr) 
0.007645 seconds (4 allocations: 160 bytes) 

@time testB!(arr2) 
0.007704 seconds (4 allocations: 160 bytes) 

, które zasadniczo są równoważne.

Powiązane problemy