[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
( 문서 , 블로그 링크 ).
bsxfun
보다 빠름repmat
(아래 참조)bsxfun
타이핑이 덜 필요합니다- 를 사용하는
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
임의의 연산자를 적용 할 수 있습니다. 부수적으로, 그것이 bsxfun
BLAS 외부 제품만큼 빠르다는 것을 보는 것은 매우 흥미 롭습니다 . 그리고 BLAS는 일반적으로 성능 을 제공 하는 것으로 간주됩니다 .
답변
R2016b부터 Matlab은 다양한 연산자에 대한 암시 적 확장 을 지원 하므로 대부분의 경우 더 이상 사용할 필요가 없습니다 bsxfun
.
이전에는이 기능을 통해이 기능을 사용할 수있었습니다
bsxfun
. 이제 암시 적 확장bsxfun
을 지원하는 함수 및 연산자에 대한 직접 호출로 대부분의 용도를 대체하는 것이 좋습니다 . 사용에 비해 , 암시 적 확장 이벤트 빠른 속도 ,
더 나은 메모리 사용 및 코드의 가독성을 높이기 .bsxfun
있다 상세한 논의 의 암시 적 확장 과 로렌의 블로그에 그 성능은. MathWorks에서 Steve Eddins 를 인용 하려면 :
R2016b에서 암시 적 확장 은
bsxfun
대부분의 경우 보다 빠르거나 빠르게 작동합니다 . 암시 적 확장 의 최상의 성능 향상 은 작은 매트릭스 및 배열 크기입니다. 큰 행렬 크기의 경우 암시 적 확장은와 거의 같은 속도 인 경향이 있습니다bsxfun
.
답변
상황이 항상 세 가지 일반적인 방법 인 repmat
, 색인에 의한 지출 및 bsxfun
. 벡터 크기를 더 늘리면 오히려 더 흥미로워집니다. 줄거리 참조 :
bsxfun
실제로 어느 시점에서 다른 두 개보다 약간 느려 지지만 벡터 크기를 훨씬 더 늘리면 (> 13E6 출력 요소) bsxfun이 갑자기 다시 약 3 배 빨라집니다. 그들의 속도는 단계적으로 뛰어 오르고 순서가 항상 일치하지는 않습니다. 내 생각 엔 프로세서 / 메모리 크기에 따라 다를 수 있지만 일반적으로 bsxfun
가능할 때마다 붙어 있다고 생각 합니다.