[arrays] Matlab에서 bsxfun을 사용하는 것이 언제 최적입니까?

내 질문 : 나는 Matlab 질문에 대한 많은 좋은 대답이 종종 함수를 사용한다는 것을 알았습니다 bsxfun. 왜?

동기 : 에 대한 Matlab 문서 bsxfun에서 다음 예제가 제공됩니다.

A = magic(5);
A = bsxfun(@minus, A, mean(A))

물론 우리는 다음을 사용하여 동일한 작업을 수행 할 수 있습니다.

A = A - (ones(size(A, 1), 1) * mean(A));

실제로 간단한 속도 테스트는 두 번째 방법이 약 20 % 빠릅니다. 첫 번째 방법을 사용하는 이유는 무엇입니까? bsxfun“수동”접근 방식보다 사용 속도가 훨씬 빠른 환경이 있다고 생각 합니다. 나는 그러한 상황의 예와 그것이 더 빠른 이유에 대한 설명을 보는 데 정말로 관심이 있습니다.

또한 Matlab 문서에서 다시 한 번이 질문에 대한 하나의 마지막 요소는 다음과 bsxfun같습니다. “C = bsxfun (fun, A, B)는 함수 핸들 fun에 의해 지정된 요소 별 이진 연산을 단일 배열을 사용하여 배열 A 및 B에 적용합니다. 확장 가능. ” “싱글 톤 확장 사용”이라는 문구는 무엇을 의미합니까?



답변

내가 사용하는 세 가지 이유가 있습니다 bsxfun( 문서 , 블로그 링크 ).

  1. bsxfun보다 빠름 repmat(아래 참조)
  2. bsxfun 타이핑이 덜 필요합니다
  3. 를 사용하는 bsxfun것처럼을 사용 accumarray하면 Matlab에 대한 이해가 좋아집니다.

bsxfun입력 배열을 “단일 차원”, 즉 배열의 크기가 1 인 차원을 따라 복제하여 다른 배열의 해당 차원의 크기와 일치시킵니다. 이것이 “단일 확장”입니다. 따로, 싱글 톤 치수는 전화하면 떨어질 치수 squeeze입니다.

아주 작은 문제의 경우 repmat접근 방식이 더 빠를 수 있지만 해당 배열 크기에서는 두 작업이 너무 빨라 전체 성능 측면에서 차이가 없을 것입니다. 두 가지 중요한 이유 bsxfun가 더 빠릅니다. (1) 컴파일 된 코드에서 계산이 발생합니다. 즉, 실제 배열 복제가 발생하지 않으며 (2) bsxfun다중 스레드 Matlab 함수 중 하나입니다.

상당히 빠른 랩톱에서 R2012b repmat와 속도를 비교했습니다 bsxfun.

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

나를 위해 bsxfun보다 약 3 배 빠릅니다 repmat. 배열이 커지면 차이가 더 뚜렷해집니다.

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

런타임시 점프 repmat는 1Mb의 배열 크기 에서 발생하며 프로세서 캐시의 크기와 관련이있을 수 있습니다 bsxfun. 출력 배열 만 할당하면되므로 점프가 나쁘지 않습니다.

아래에는 타이밍에 사용한 코드가 있습니다.

n = 300;
k=1; %# k=100 for the second graph
a = ones(10,1);
rr = zeros(n,1);
bb=zeros(n,1);
ntt=100;
tt=zeros(ntt,1);
for i=1:n;
   r = rand(1,i*k);
   for it=1:ntt;
      tic,
      x=bsxfun(@plus,a,r);
      tt(it)=toc;
   end;
   bb(i)=median(tt);
   for it=1:ntt;
      tic,
      y=repmat(a,1,i*k)+repmat(r,10,1);
      tt(it)=toc;
   end;
   rr(i)=median(tt);
end


답변

필자의 경우 bsxfun열 또는 행 문제에 대해 생각할 필요가 없으므로 사용 합니다.

예를 작성하려면 다음을 수행하십시오.

A = A - (ones(size(A, 1), 1) * mean(A));

몇 가지 문제를 해결해야합니다.

1) size(A,1)또는size(A,2)

2) ones(sizes(A,1),1)또는ones(1,sizes(A,1))

3) ones(size(A, 1), 1) * mean(A)또는mean(A)*ones(size(A, 1), 1)

4) mean(A)또는mean(A,2)

을 사용할 때 bsxfun마지막 것을 해결해야합니다.

a) mean(A)또는mean(A,2)

당신은 게으른 또는 뭔가 생각하지만 사용할 때 bsxfun, 나는이 적은 버그를 내가 빨리 프로그램 .

또한 타이핑 속도가독성 이 향상 됩니다 .


답변

매우 흥미로운 질문입니다! 나는 최근 에이 질문에 대답하면서 정확히 그러한 상황을 우연히 발견했습니다 . 벡터를 통해 크기가 3 인 슬라이딩 윈도우의 인덱스를 계산하는 다음 코드를 고려하십시오 a.

a = rand(1e7,1);

tic;
idx = bsxfun(@plus, [0:2]', 1:numel(a)-2);
toc

% equivalent code from im2col function in MATLAB
tic;
idx0 = repmat([0:2]', 1, numel(a)-2);
idx1 = repmat(1:numel(a)-2, 3, 1);
idx2 = idx0+idx1;
toc;

isequal(idx, idx2)

Elapsed time is 0.297987 seconds.
Elapsed time is 0.501047 seconds.

ans =

 1

이 경우 bsxfun거의 두 배 더 빠릅니다! 이 때문에 유용하고 빠른 메모리를 명시 적으로 할당 방지 행렬에 대한을 idx0하고 idx1바로 추가 할 다시 읽기 다음 메모리에 저장하고,. 메모리 대역폭은 귀중한 자산이자 오늘날 아키텍처의 병목 현상이므로 현명하게 사용하고 코드의 메모리 요구 사항을 줄여 성능을 향상 시키려고합니다.

bsxfun벡터를 복제하여 얻은 두 개의 행렬을 명시 적으로 조작하는 대신 두 벡터의 모든 요소 쌍에 임의 연산자를 적용하여 행렬을 만듭니다. 이것이 싱글 톤 확장 입니다. BLAS 의 외부 제품 으로 생각할 수도 있습니다 .

v1=[0:2]';
v2 = 1:numel(a)-2;
tic;
vout = v1*v2;
toc
Elapsed time is 0.309763 seconds.

두 벡터를 곱하여 행렬을 얻습니다. 외부 제품은 곱셈 만 수행하며 bsxfun임의의 연산자를 적용 할 수 있습니다. 부수적으로, 그것이 bsxfunBLAS 외부 제품만큼 빠르다는 것을 보는 것은 매우 흥미 롭습니다 . 그리고 BLAS는 일반적으로 성능 을 제공 하는 것으로 간주됩니다 .

편집 Dan의 의견에 감사 합니다. Loren의 정확한 기사 는 다음과 같습니다 .


답변

R2016b부터 Matlab은 다양한 연산자에 대한 암시 적 확장 을 지원 하므로 대부분의 경우 더 이상 사용할 필요가 없습니다 bsxfun.

이전에는이 ​​기능을 통해이 기능을 사용할 수있었습니다 bsxfun. 이제 암시 적 확장bsxfun 을 지원하는 함수 및 연산자에 대한 직접 호출로 대부분의 용도를 대체하는 것이 좋습니다 . 사용에 비해 , 암시 적 확장 이벤트 빠른 속도 ,
더 나은 메모리 사용코드의 가독성을 높이기 .bsxfun

있다 상세한 논의암시 적 확장 과 로렌의 블로그에 그 성능은. MathWorks에서 Steve Eddins 를 인용 하려면 :

R2016b에서 암시 적 확장bsxfun대부분의 경우 보다 빠르거나 빠르게 작동합니다 . 암시 적 확장 의 최상의 성능 향상 은 작은 매트릭스 및 배열 크기입니다. 큰 행렬 크기의 경우 암시 적 확장은와 거의 같은 속도 인 경향이 있습니다 bsxfun.


답변

상황이 항상 세 가지 일반적인 방법 인 repmat, 색인에 의한 지출 및 bsxfun. 벡터 크기를 더 늘리면 오히려 더 흥미로워집니다. 줄거리 참조 :

비교

bsxfun실제로 어느 시점에서 다른 두 개보다 약간 느려 지지만 벡터 크기를 훨씬 더 늘리면 (> 13E6 출력 요소) bsxfun이 갑자기 다시 약 3 배 빨라집니다. 그들의 속도는 단계적으로 뛰어 오르고 순서가 항상 일치하지는 않습니다. 내 생각 엔 프로세서 / 메모리 크기에 따라 다를 수 있지만 일반적으로 bsxfun가능할 때마다 붙어 있다고 생각 합니다.


답변