2011-09-27 5 views
7

저는 MATLAB에서 프로그래밍을하고 있었고, 권장대로 항상 벡터화를 사용하려고합니다. 그러나 결국 프로그램은 상당히 느려졌습니다. 그래서 한 곳에서 루프를 사용할 때 코드가 훨씬 빨라진다는 것을 알았습니다 (아래 예 참조).for '루프와 MATLAB의 벡터화

이 경우 성능이 중요하기 때문에 내가 잘못 해석했거나 잘못했는지 알고 싶습니다. 벡터화 또는 루프가 빨라지면 추측을 계속하고 싶지 않습니다.

% data initialization 

k = 8; 
n = 2^k+1; 
h = 1/(n-1); 
cw = 0.1; 

iter = 10000; 

uloc = zeros(n); 
fploc = uloc; 
uloc(2:end-1,2:end-1) = 1; 
vloc = uloc; 
ploc = ones(n); 

uloc2 = zeros(n); 
fploc2 = uloc2; 
uloc2(2:end-1,2:end-1) = 1; 
vloc2 = uloc2; 
ploc2 = ones(n); 

%%%%%%%%%%%%%%%%%%%%%% 
% vectorized version % 
%%%%%%%%%%%%%%%%%%%%%% 
tic 
for it=1:iter 
    il=2:4; 
    jl=2:4; 
    fploc(il,jl) = h/6*(-uloc(il-1,jl-1) + uloc(il-1,jl)... 
     -2*uloc(il,jl-1)+2*uloc(il,jl+1)... 
     -uloc(il+1,jl) + uloc(il+1,jl+1)... 
     ... 
     -vloc(il-1,jl-1) - 2*vloc(il-1,jl)... 
     +vloc(il,jl-1) - vloc(il,jl+1)... 
     + 2*vloc(il+1,jl) + vloc(il+1,jl+1))... 
     ... 
     +cw*h^2*(-ploc(il-1,jl)-ploc(il,jl-1)+4*ploc(il,jl)... 
     -ploc(il+1,jl)-ploc(il,jl+1)); 
end 
toc 


%%%%%%%%%%%%%%%%%%%%%% 
% loop version % 
%%%%%%%%%%%%%%%%%%%%%% 
tic 
for it=1:iter 
    for il=2:4 
     for jl=2:4 
      fploc2(il,jl) = h/6*(-uloc2(il-1,jl-1) + uloc2(il-1,jl)... 
       -2*uloc2(il,jl-1)+2*uloc2(il,jl+1)... 
       -uloc2(il+1,jl) + uloc2(il+1,jl+1)... 
       ... 
       -vloc2(il-1,jl-1) - 2*vloc2(il-1,jl)... 
       +vloc2(il,jl-1) - vloc2(il,jl+1)... 
       + 2*vloc2(il+1,jl) + vloc2(il+1,jl+1))... 
       ... 
       +cw*h^2*(-ploc2(il-1,jl)-ploc2(il,jl-1)+4*ploc2(il,jl)... 
       -ploc2(il+1,jl)-ploc2(il,jl+1)); 
     end 
    end 
end 
toc 

답변

6

내가 코드를 통과하지 못했지만, matlab에 최신 버전의 JIT 컴파일러는 당신이 직면하고있는 상황은 매우 일반적입니다 지점으로 개선 - 루프는 벡터화 된 코드보다 빠를 수 있습니다. 사전에 어떤 것이 더 빠를 것인지를 아는 것은 어렵 기 때문에 코드를 가장 자연스러운 방식으로 작성하고 프로파일 링 한 다음 병목 현상이있는 경우 루프에서 벡터화 (또는 다른 방법)로 전환 해보십시오.

2

아마도 일부 요소의 매트릭스는 벡터화 효율성을 테스트하는 좋은 방법이 아닙니다. 결국 그것은 잘 작동하는 응용 프로그램에 달려 있습니다.

또한 일반적으로 벡터화 된 코드는 기본 모델보다 우수하지만 모양이 좋지 않은 경우가 많으며 구현이 손 상됩니다. 당신이 한 일은 지금 당신에게 가장 잘 맞는 것이 무엇인지 알기 때문에 훌륭합니다.

6

MATLAB의 Just in Time 컴파일러 (JIT)가 지난 2 년 동안 크게 향상되었습니다. 그리고 비록 당신이 일반적으로 코드를 벡터화해야한다는 것이 맞지만, 내 경험에 의하면 이것은 특정 연산과 함수에만 해당되며 함수가 처리하는 데이터의 양에 따라 달라집니다.

최상의 결과를 얻으려면 벡터화가 있거나없는 profile your MATLAB code을 사용하는 것이 가장 좋습니다.

+0

당신이 "얼마나 많은 데이터를 가지고 있느냐에 달려있다"라고 말하면, 당신이 의미하는 바에 대해 좀 더 구체적이겠습니까? 일반적으로 루프가 더 큰 데이터 세트로 인해 성능이 저하된다는 의미였습니까? –

0

저는이 벡터화를 부르지 않을 것입니다.

필터링 작업을하는 것처럼 보입니다. 이러한 필터의 진정한 벡터화 된 버전은 필터 매트릭스 (즉 for 루프 전체를 나타내는 하나의 매트릭스)를 곱한 원래 데이터입니다.

이러한 매트릭스의 문제점은 너무 희박하기 때문에 (대각선 주위의 소수의 0이 아닌 요소 만) 사용하기가 거의 어렵다는 것입니다. sparse 명령을 사용할 수 있지만 그때조차도 표기법의 우아함은 아마도 필요한 추가 메모리를 정당화하지 못합니다.

루프 카운터 등이 여전히 복잡한 행렬로 취급되기 때문에 Matlab은 for 루프에서 사용하기가 어려웠 기 때문에 이러한 행렬에 대한 모든 검사가 매 반복마다 평가되었습니다. 내 생각 엔 당신의 for 루프 안에는 필터 계수를 적용 할 때마다 모든 검사가 여전히 수행된다는 것입니다.

아마도 matlab 함수 filterfilter2이 여기에 유용할까요? 당신은이 게시물을 읽을 수도 있습니다 : Improving MATLAB Matrix Construction Code : Or, code Vectorization for begginers

0

하나의 가능한 설명은 시작 오버 헤드입니다. 임시 매트릭스가 장면 뒤에 생성되면 메모리 할당을 준비하십시오. 또한, MATLAB은 행렬이 작아서 루프 오버 헤드가 있다는 것을 추론 할 수 없다고 생각합니다.그래서 벡터화 된 버전은 작업의 알려진 숫자로 비교해

double* tmp=(double*)malloc(n*sizeof(double)); 
for(size_t k=0;k<N;++k) 
    { 
// Do stuff with elements 
    } 
free(tmp); 

같은 코드에 끝낼 수 있습니다 :

double temp[2]; 
temp[0]=...; 
temp[1]=...; 

malloc이-loopcounter없는 시간이 긴 경우 따라서 JIT는 빠를 수 있습니다 각 계산에 대한 작업량에 비해