Programing

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

lottogame 2020. 7. 1. 07:59
반응형

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)

When I use bsxfun, I just have to solve the last one:

a) mean(A) or mean(A,2)

You might think it is lazy or something, but when I use bsxfun, I have less bugs and I program faster.

Moreover, it is shorter, which improves typing speed and readability.


Very interesting question! I have recently stumbled upon exactly such situation while answering this question. Consider the following code that computes indices of a sliding window of size 3 through a vector 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

In this case bsxfun is almost twice faster! It is useful and fast because it avoids explicit allocation of memory for matrices idx0 and idx1, saving them to the memory, and then reading them again just to add them. Since memory bandwidth is a valuable asset and often the bottleneck on todays architectures, you want to use it wisely and decrease the memory requirements of your code to improve the performance.

bsxfun allows you to do just that: create a matrix based on applying an arbitrary operator to all pairs of elements of two vectors, instead of operating explicitly on two matrices obtained by replicating the vectors. That is singleton expansion. You can also think about it as the outer product from BLAS:

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

You multiply two vectors to obtain a matrix. Just that the outer product only performs multiplication, and bsxfun can apply arbitrary operators. As a side note, it is very interesting to see that bsxfun is as fast as the BLAS outer product. And BLAS is usually considered to deliver the performance..

Edit Thanks to Dan's comment, here is a great article by Loren discussing exactly that.


As of R2016b, Matlab supports Implicit Expansion for a wide variety of operators, so in most cases it is no longer necessary to use bsxfun:

Previously, this functionality was available via the bsxfun function. It is now recommended that you replace most uses of bsxfun with direct calls to the functions and operators that support implicit expansion. Compared to using bsxfun, implicit expansion offers faster speed, better memory usage, and improved readability of code.

There's a detailed discussion of Implicit Expansion and its performance on Loren's blog. To quote Steve Eddins from MathWorks:

In R2016b, implicit expansion works as fast or faster than bsxfun in most cases. The best performance gains for implicit expansion are with small matrix and array sizes. For large matrix sizes, implicit expansion tends to be roughly the same speed as bsxfun.


Things are not always consistent with the 3 common methods: repmat, expension by ones indexing, and bsxfun. It gets rather more interesting when you increase the vector size even further. See plot:

비교

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

참고 URL : https://stackoverflow.com/questions/12951453/in-matlab-when-is-it-optimal-to-use-bsxfun

반응형