LangDev

Matlab 코딩도 나름대로(?) 할만 하네요

mithrandir

zero crossing (신호 데이터가 있을때, 0을 지나치는 것, 즉 해라고 봐도 되고 부호가 바뀐다고 봐도 되고)을 구하기 위해 imperative하게 생각하면

signal = [.....]
N = length(signal);
zerocross = 0;
for i=1:N-1
  if signal(i) * signal(i+1) < 0
    zerocross = zerocross + 1;
  end
end

이러면 엄청 느려서 견딜 수가 없어요.

그래서 찾은 방법이,

N = length(signal);
zerocross = sum((signal(1:N-1) .* signal(2:N)) < 0);

되도록이면 벡터 그대로, 매트릭스 그대로 다루려고 생각하다 보면 생각도 좀 편해지는 것 같아요. 느려터진 for 쓸 일도 거의 없어지고요.

Matlab에서 .* 연산자는 무엇인가요?

홍민희

Vector OP Numeric 은 각 벡터 원소에 대해서 연산을 수행하는데, Vector OP Vector가 되면 선형대수 같은데서 보는 행렬연산을 하게 되요. (Vector 자리에 Matrix가 와도 마찬가지). 그런데 .OP 처럼 써주면 각 원소 1:1로 연산을 하게 되죠.

mithrandir

1:1로 연산한다는 것은, 각 시퀀스의 동일 위치에 있는 원소끼리 연산한다는 뜻인가요?

홍민희

*은 내적인가요 외적인가요? (왠지 외적일 것 같은 느낌이...)

lifthrasiir

Haskell로 표현하면 아래와 같은 뜻인가요?;

signal = [...]
zerocross = length [ (x, y) | (x, y) <- zip (init signal) (tail signal), x * y < 0 ]
홍민희

맞아요. 바로 그거에요.

mithrandir

암시적으로나 명시적으로 벡터화가 가능한 코드를 쉽게 짤 수 있으면 최적화도 쉬워지겠죠. 벡터는 기본적으로 SIMD나 병렬화의 대상이 될 수 있는 거니까... 첫 코드가 느렸던 이유는 Matlab이 for 루프를 별도로 vectorization하지 않거나, 벡터 연산이 충분히 최적화되어 있거나, 둘 다거나 셋 중 하나겠죠.

lifthrasiir

이번 학기에 artificial neural network 수업을 듣는데 실습을 모두 matlab으로 했어요. 거기서도 되도록이면 for loop 대신 matlab의 행렬 연산을 바로 이용하라고 했는데, 처음엔 잘 적응이 안 되다가 어느 정도 하고 나니 더 편하게 느껴지더라구요.

아침놀

저는 수학과 사람들과 같이 작업할 일이 있었는데 그들이 작성한 Matlab code를 보고 많이 당황했었습니다. 제가 하는 것이라고는 Matlab code와 작성해준 기술서(algorithm)을 C로 작성하는 것이었는데 C로 작성한 제 program이 훨씬 느려서 놀랬었습니다.

무조건 작게 유지하는 것이 cache hit율도 올라가고, 여러모로 좋다는 편견이 무너졌었죠.

더욱이 행렬을 그대로 적용하는 방식은 for 반복등을 없애기 때문에 side effect 역시 많이 사라졌습니다. 함수형 언어가 강조하는 점을 그때서야 알게 되었죠.

흥미로운 점은 수학과에서 작성해준 기술서는 전산학에서 흔히 하는 for 반복을 통해서 기술되어 있었는데 오류가 있고, 직관적이지 않아서(C style이 아니어서?) 이래저래 혼란이 많았었습니다.

Side effect 때문에 발생하는 앞뒤 순서의 의존성을 정확히 생각하지 않고 기술된 경우가 있었죠. 그것 외에도 여러가지 문제점이 있었던 것 같은데...

김우승