수색…


비고

  • 프로파일 링 코드는 최적화 작업을 실제로 정당화하는 코드 부분에 개발자를 집중시킴으로써 " 조기 최적화 "라는 두려운 연습을 피하는 방법입니다.
  • " 프로그램 성능 측정 "이라는 제목의 MATLAB 문서

프로파일 러를 사용하여 성능 병목 현상 식별

MATLAB Profiler 는 MATLAB 코드의 소프트웨어 프로파일 링 을위한 도구입니다. 프로파일 러를 사용하면 실행 시간과 메모리 소비를 시각적으로 표시 할 수 있습니다.

프로파일 러의 실행은 두 가지 방법으로 수행 할 수 있습니다.

  • 편집기에 .m 파일이 열려있는 동안 MATLAB GUI에서 "Run and Time"버튼을 클릭하십시오 ( R2012b추가됨 ).

    도구 상자의 단추

  • 프로그래밍 방식으로 다음을 사용 :

    profile on
    <some code we want to test>
    profile off
    

아래는 몇 가지 샘플 코드와 프로파일 링 결과입니다.

function docTest

for ind1 = 1:100
  [~] = var(...
            sum(...
                randn(1000)));
end

spy

프로파일 러 출력

위에서 spy 함수는 총 실행 시간의 약 25 %를 차지한다는 것을 알 수 있습니다. "실제 코드"의 경우 최적화를 피하는 varcla 와 유사한 함수가 아니라 실행 시간의 많은 부분을 차지하는 함수가 최적의 후보가 될 수 있습니다.

또한 함수 이름 열의 항목을 클릭하면 해당 항목의 실행 시간에 대한 자세한 분석을 볼 수 있습니다. 다음은 spy 클릭의 예입니다.

"스파이"의 내부 타이밍


프로파일 러를 실행하기 전에 profile('-memory') 을 실행하여 메모리 소비량을 프로파일 링 할 수도 있습니다.

여기에 이미지 설명을 입력하십시오.

여러 함수의 실행 시간 비교

널리 사용되는 tictoc 조합은 함수 또는 코드 스 니펫의 실행 시간에 대한 대략적인 아이디어를 제공 할 수 있습니다.

여러 기능을 비교하기 위해 사용해서는 안됩니다. 왜? 위의 솔루션을 사용하여 스크립트 내에서 비교할 모든 코드 스 니펫에 대해 동일한 조건 을 제공하는 것은 거의 불가능합니다. 어쩌면 함수가 동일한 함수 공간과 공통 변수를 공유하기 때문에 나중에 호출 된 함수와 코드 스 니펫은 이미 이전에 초기화 된 변수와 함수를 이용합니다. 또한 JIT 컴파일러가 이후에 호출 된 스 니펫을 똑같이 처리할지 여부에 대한 통찰력이 없습니다.


벤치 마크 전용 기능은 timeit 입니다. 다음 예제에서는 그 사용법을 보여줍니다.

배열 A 와 행렬 B 있습니다. B 어떤 행이 다른 원소의 수를 세어 A 와 가장 유사한 지 결정해야합니다.

function t = bench()
    A = [0 1 1 1 0 0];
    B = perms(A);

    % functions to compare
    fcns = {
        @() compare1(A,B);
        @() compare2(A,B);
        @() compare3(A,B);
        @() compare4(A,B);
    };

    % timeit
    t = cellfun(@timeit, fcns);
end

function Z = compare1(A,B)  
    Z = sum(  bsxfun(@eq,  A,B) , 2);
end
function Z = compare2(A,B)  
    Z = sum(bsxfun(@xor, A, B),2);
end
function Z = compare3(A,B)  
    A = logical(A);
    Z = sum(B(:,~A),2) + sum(~B(:,A),2);
end
function Z = compare4(A,B)  
     Z = pdist2( A, B, 'hamming', 'Smallest', 1 );
end

이 벤치 마크 방법은 이 대답 에서 처음 발견되었습니다.

`싱글 '이 되어도 괜찮아!

개요 :

MATLAB의 숫자 배열에 대한 기본 데이터 유형은 double 입니다. double숫자부동 소수점 표현이며이 형식은 값 당 8 바이트 (또는 64 비트)를 사용합니다. 예를 들어, 정수 또는 숫자의 불안정성이 급박 한 문제가 아닌 경우, 높은 비트 깊이가 필요하지 않을 수 있습니다 만 다루는 경우,합니다. 이러한 이유로 single 정밀도 (또는 다른 적절한 유형 )의 이점을 고려하는 것이 좋습니다.

  • 실행 시간 단축 (특히 GPU에서 눈에 띄는).
  • 메모리 소비량의 절반 : 메모리 부족 오류로 인해 double 실패한 경우 성공할 수 있습니다. 파일로 저장할 때 더욱 컴팩트합니다.

지원되는 데이터 유형의 변수를 single 변수로 변환하는 작업은 다음을 사용하여 수행됩니다.

sing_var = single(var);

기본적으로 double 값을 출력하는 일반적으로 사용되는 함수 (예 : zeros , eye , ones )는 출력의 유형 / 클래스를 지정할 수 있습니다.

스크립트의 변수를 기본이 아닌 정밀도 / 유형 / 클래스로 변환 :

2016 년 7 월부터는 기본 MATLAB 데이터 유형을 double 에서 변경할 수있는 문서화 된 방법이 없습니다.

MATLAB에서 새 변수는 일반적으로 변수를 만들 때 사용되는 변수의 데이터 유형을 모방합니다. 이를 설명하기 위해 다음 예제를 고려하십시오.

A = magic(3);
B = diag(A);
C = 20*B;
>> whos C
  Name      Size            Bytes  Class     Attributes
  C         3x1                24  double 
A = single(magic(3)); % A is converted to "single"
B = diag(A);
C = B*double(20);     % The stricter type, which in this case is "single", prevails
D = single(size(C));  % It is generally advised to cast to the desired type explicitly.
>> whos C
  Name      Size            Bytes  Class     Attributes
  C         3x1                12  single  

따라서 코드 전체에 변경 사항이 침투하도록 여러 초기 변수를 변환 / 변환하는 것으로 충분할 수도 있습니다. 그러나 이것은 권장하지 않습니다 (아래의 주의 사항 및 함점 참조).

주의 사항 및 함정 :

  1. 반복적 인 변환은 숫자 소음 ( single 에서 double ) 또는 정보 손실 ( double 에서 single 로 또는 특정 정수 유형 사이에서 변환)의 도입으로 인해 권장 되지 않습니다 . 예 :

    double(single(1.2)) == double(1.2)   
    ans =
         0
    

    이것은 typecast 사용하여 다소 완화 할 수 있습니다. 부동 소수점 부정확성에 유의하십시오 .

  2. 암시적인 데이터 유형 지정 (즉, MATLAB이 계산 결과의 유형을 추측해야하는 것)에만 의존하는 것은 바람직하지 않은 여러 가지 영향으로 인해 권장 되지 않습니다 .

    • 정보 손실 : double 결과가 예상되지만 singledouble 피연산자를 부주의하게 조합하면 single 정밀도가 산출됩니다.

    • 예기치 않게 높은 메모리 소비 : single 결과가 예상되지만 부주의 한 계산 결과가 double 출력되는 경우.

    • GPU로 작업 할 때 불필요한 오버 헤드 : gpuArray 유형 (예 : VRAM에 저장된 변수)과 비 gpuArray 변수 (예 : RAM에 일반적으로 저장된 변수)를 혼합 할 때 계산을 수행하기 전에 데이터를 한 방향으로 전송해야합니다. 이 작업은 시간이 걸리고 반복 계산에서 매우 두드러 질 수 있습니다.

    • 부동 소수점 유형을 정수 유형과 혼합 할 때 발생하는 오류 : 정수 및 부동 소수점 유형의 혼합 입력에 대해 mtimes ( * )와 같은 함수가 정의되지 않으며 오류가 발생합니다. times ( .* )과 같은 함수는 정수 유형 입력에 대해 전혀 정의되지 않으며 다시 오류가 발생합니다.

      >> ones(3,3,'int32')*ones(3,3,'int32')
      Error using  * 
      MTIMES is not fully supported for integer classes. At least one input must be scalar.
      
      >> ones(3,3,'int32').*ones(3,3,'double')
      Error using  .* 
      Integers can only be combined with integers of the same class, or scalar doubles.
      

    코드의 가독성을 높이고 원치 않는 유형의 위험을 줄이려면 변수가 원하는 유형 으로 명시 적으로 변환되는 방어적인 방법을 사용하는 것이 좋습니다 .


참조 :

ND 배열을 재정렬하면 전체 성능이 향상 될 수 있습니다.

어떤 경우에는 ND 배열 집합에 함수를 적용해야합니다. 이 간단한 예제를 살펴 보겠습니다.

A(:,:,1) = [1 2; 4 5];
A(:,:,2) = [11 22; 44 55];
B(:,:,1) = [7 8; 1 2];
B(:,:,2) = [77 88; 11 22];

A =

ans(:,:,1) =

   1   2 
   4   5 

ans(:,:,2) =

   11   22
   44   55

>> B
B =

ans(:,:,1) =

   7   8
   1   2

ans(:,:,2) =

   77   88
   11   22

두 행렬 모두 3D입니다. 다음을 계산해야한다고 가정 해 봅시다.

result= zeros(2,2);
...
for k = 1:2 
   result(i,j) = result(i,j) + abs( A(i,j,k) - B(i,j,k) );
...

if k is very large, this for-loop can be a bottleneck since MATLAB order the data in a column major fashion. So a better way to compute "result" could be:

% trying to exploit the column major ordering
Aprime = reshape(permute(A,[3,1,2]), [2,4]);
Bprime = reshape(permute(B,[3,1,2]), [2,4]);


>> Aprime
Aprime =

    1    4    2    5
   11   44   22   55

>> Bprime
Bprime =

    7    1    8    2
   77   11   88   22

이제 우리는 위의 루프를 다음과 같이 대체합니다.

result= zeros(2,2);
....
temp = abs(Aprime - Bprime);
for k = 1:2
    result(i,j) = result(i,j) + temp(k, i+2*(j-1));
...

우리는 캐시 메모리를 활용할 수 있도록 데이터를 재정렬했습니다. 순열 (permutation)과 변형 (reshape)은 비용이 많이 들지만 큰 ND 배열로 작업 할 때 이러한 연산과 관련된 계산 비용은 배열이 아닌 배열로 작업하는 것보다 훨씬 적습니다.

사전 할당의 중요성

MATLAB의 배열은 메모리의 연속 블록으로 유지되며 MATLAB에 의해 자동으로 할당 및 해제됩니다. MATLAB은 사용하기 쉬운 구문 뒤에 배열의 크기 조정과 같은 메모리 관리 작업을 숨 깁니다.

a = 1:4

a =

     1     2     3     4

a(5) = 10  % or alternatively a = [a, 10]

a =

     1     2     3     4    10

위의 작업은 간단한 작업이 아니라는 것을 이해하는 것이 중요합니다 a(5) = 10 인해 MATLAB은 크기 5의 새 메모리 블록을 할당하고 처음 4 개의 숫자를 복사 한 다음 5를 10으로 설정합니다. 그것은 O(numel(a)) 연산이며 O(1) 아닙니다.

다음을 고려하세요:

clear all
n=12345678;
a=0;
tic
for i = 2:n
    a(i) = sqrt(a(i-1)) + i;
end
toc

Elapsed time is 3.004213 seconds.

a 는이 루프에서 n 번 재 할당됩니다 (MATLAB이 수행하는 최적화 제외)! MATLAB은 우리에게 경고를줍니다 :

"변수 'a'는 모든 루프 반복마다 크기가 변경되는 것으로 보입니다. 속도를 사전 할당하는 것이 좋습니다."

우리가 미리 할당하면 어떻게됩니까?

a=zeros(1,n);
tic
for i = 2:n
    a(i) = sqrt(a(i-1)) + i;
end
toc

Elapsed time is 0.410531 seconds.

우리는 실행 시간이 몇 배 줄어든 것을 볼 수 있습니다.

사전 할당 방법 :

MATLAB은 사용자의 특정 요구 사항에 따라 벡터 및 행렬을 할당하는 다양한 기능을 제공합니다. 이들은 다음을 포함한다 : zeros , ones , nan , eye , true

a = zeros(3)       % Allocates a 3-by-3 matrix initialized to 0
a =

     0     0     0
     0     0     0
     0     0     0

a = zeros(3, 2)     % Allocates a 3-by-2 matrix initialized to 0
a =

     0     0
     0     0
     0     0

a = ones(2, 3, 2)      % Allocates a 3 dimensional array (2-by-3-by-2) initialized to 1
a(:,:,1) =

     1     1     1
     1     1     1


a(:,:,2) =

     1     1     1
     1     1     1

a = ones(1, 3) * 7  % Allocates a row vector of length 3 initialized to 7
a =

     7     7     7

데이터 유형을 지정할 수도 있습니다.

a = zeros(2, 1, 'uint8');  % allocates an array of type uint8

기존 어레이의 크기를 복제하는 것도 쉽습니다.

a = ones(3, 4);       % a is a 3-by-4 matrix of 1's
b = zeros(size(a));  % b is a 3-by-4 matrix of 0's

그리고 유형을 복제하십시오 :

a = ones(3, 4, 'single');       % a is a 3-by-4 matrix of type single
b = zeros(2, 'like', a);        % b is a 2-by-2 matrix of type single

'유사'는 또한 복잡성희소성을 복제한다는 점에 유의하십시오.

사전 할당은 암시 적으로 같은 최종 필요한 크기의 배열을 반환하는 모든 기능을 사용하여 달성 rand , gallery , kron , bsxfun , colon 및 많은 다른 사람을. 예를 들어, 선형으로 변하는 요소로 벡터를 할당하는 일반적인 방법은 콜론 연산자 (2 또는 3 피연산자 변형 1 포함 )을 사용하는 것입니다.

a = 1:3 
a =

     1     2     3

a = 2:-3:-4
a =

     2    -1    -4

셀 배열은 zeros() 과 거의 같은 방법으로 cell() 함수를 사용하여 할당 할 수 있습니다.

a = cell(2,3)
a = 

    []    []    []
    []    []    []

셀 배열은 셀 내용의 메모리에있는 위치에 대한 포인터를 보유함으로써 작동합니다. 따라서 모든 사전 할당 팁은 개별 셀 배열 요소에도 적용됩니다.


추가 읽기 :



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow