8

는 다음과 같은 기능을 고려불필요한 할당

x = rand(30,30,100000) 
b = rand(100000) 
@time mytest(x,b) 

elapsed time: 0.571765222 seconds (727837732 bytes allocated, 66.49% gc time) 

왜 그렇게 많은 메모리 및 지출 너무 많은 시간을 할당한다 : 나는 그것을 실행하면

function mytest(x, b) 
    y = zeros(x[:,:,1]) 
    for i in 1:length(b) 
     y += b[i] * x[:,:,i] 
    end 
    return y 
end 

, 나는 다음과 같은 수 가비지 수집을하고 있습니까? 코드는 유형이 안정해야하며 += 연산자가 재 할당을 수행하지 않을 것으로 예상됩니다. 그러나 두 개의 행렬을 추가 할 때마다 다시 할당하는 것으로 보입니다.

줄리아의 버그라고 생각합니까? 그리고 더 중요한 것은 어떻게 재 할당하지 않는 방식으로이 코드를 작성할 수 있습니까?

수정 : 고정 오타.

+1

우변'b [i] * x [:, :, i]'는 먼저 제품의 결과가 왼쪽에 추가되기 전에 임시 배열을 할당합니다. 그런 다음 임시 배열을 가비지 수집해야합니다. 적어도 ... 그것이 [tag : numpy]와 함께 작동하는 방법입니다. –

+3

@moarningsun, 팁 주셔서 감사합니다. 퍼포먼스에 중점을두고있는 필자의 경험은 주로 C++과 Eigen을 사용하는데 슬라이스를 가져갈 때 임시로 할당하지 않을 것이다. 내 코드가 3 중첩 된 for 루프를 갖도록 변경했으며 할당 문제가 수정되었습니다. (그 전에는 ArrayViews 패키지를 사용해 보았지만 문제가 해결되지 않은 것 같습니다.) 더 좋은 방법이 있다면 여전히 궁금합니다. –

+1

@JimGarrison : [here] (https://groups.google.com/forum/#!topic/julia-users/i5hfGpWRHlk) 토론을 확인하십시오. '+ ='그냥 구문 설탕 (지금은 적어도) 및 그래서 난 항상 다시 할당한다고 생각하지만 (누군가가 나를 잘못 수정하십시오). 또한 세 가지 루프가 어떻게 문제를 해결하는지 보는 데 관심이 있습니다. – cd98

답변

4

@ cd98은 할당 문제를 해결하는 3 중첩 루프 솔루션을 요청했지만 동등한 벡터화 버전보다 성능이 좋지 않을 것으로 예상합니다. 여기있다 :

function mytest(x, b) 
    d1, d2, d3 = size(x) 
    y = zeros(eltype(x), d1, d2) 
    for i in 1:d3 
     for j in 1:d2 
      for k in 1:d1 
       y[k,j] += b[i] * x[k,j,i] 
      end 
     end 
    end 
    return y 
end 

x = rand(30,30,100000) 
b = rand(100000) 
@time mytest(x,b) 
@time mytest(x,b) 

그리고 출력 :

elapsed time: 0.218220119 seconds (767172 bytes allocated) 
elapsed time: 0.197181799 seconds (7400 bytes allocated) 
3

Base.Cartesian를 사용할 수있는 가능성도있다 : using Base.Cartesian 후, 당신은

@nloops 3 i x begin 
    (@nref 2 y i) += b[i_3] * (@nref 3 x i) 
end 

이 같은 기본적에 확장하는 쓸 수 있습니다 짐의 대답처럼 루프.

+1

개인적으로는 이것이 추한 것 같아 나는 짐의 해결책을 선호한다. – user4235730

4

는 (원본) 할당 문제가 해결되지 않습니다,하지만 난 단순히 @inbounds와 후자의 용액에 루프를 포장하여 1.8 배의 속도 향상에 대해 얻을 :

function mytest_inbounds(x, b) 
    d1, d2, d3 = size(x) 
    y = zeros(eltype(x), d1, d2) 
    @inbounds begin 
     for i in 1:d3 
      for j in 1:d2 
       for k in 1:d1 
        y[k,j] += b[i] * x[k,j,i] 
       end 
      end 
     end 
    end 
    return y 
end 

x = rand(30, 30, 100000) 
b = rand(100000) 
@time mytest(x, b) 
@time mytest(x, b) 
@time mytest_inbounds(x, b) 
@time mytest_inbounds(x, b) 

출력 :

elapsed time: 0.39144919 seconds (767212 bytes allocated) 
elapsed time: 0.353495867 seconds (7400 bytes allocated) 
elapsed time: 0.202614643 seconds (396972 bytes allocated) 
elapsed time: 0.193425902 seconds (7400 bytes allocated) 

또한, 여기에 관련 문제에 대한 좋은 토론의 많은 :

https://groups.google.com/forum/#!msg/julia-users/aYS_AvKqPCI/DyTiq4lKIAoJ