연산자와 함수의 반환 타입
연산자와 함수의 반환 타입 (Return Types of Operators and Functions)
희소 행렬을 쓰는 두 가지 주된 이유는 메모리 사용을 줄이고 0이 아닌 원소에 대한 계산을 피하기 위해서예요. 그런데 이 때문에 희소 연산의 결과가 언제나 희소로 돌아오는 건 아니라는 점을 알아야 해요.
출처: 문서
본문
희소 행렬을 쓰는 두 가지 기본적인 이유는 메모리 사용을 줄이는 것과 0 원소에 대해 계산을 하지 않는 것이에요. 이 둘은 서로 밀접한데, 희소 행렬 연산자나 함수의 계산 시간이 대략 0이 아닌 원소의 개수에 비례하기 때문이에요.
그래서 행렬의 0이 아닌 원소 밀도가 어느 정도 이상이 되면, 그것을 희소 행렬로 저장할 이유가 없어지고 밀집 행렬(full matrix)로 저장하는 게 맞아요. 이 때문에 밀집 행렬을 반환할 확률이 높은 연산자와 함수는 항상 밀집 행렬을 반환해요. 예를 들어 희소 행렬에 스칼라 상수를 더하면 거의 항상 밀집 행렬이 돼요. 그래서,
speye (3) + 0
⇒ 1 0 0
0 1 0
0 0 1
이 예시가 보여주듯 밀집 행렬을 반환해요.
밀집 행렬과 희소 행렬 사이의 혼합 연산자와 함수가 모두 존재하므로, 일반적으로는 문제가 생기지 않아요. 다만 문제가 생기는 한 영역이 있는데, 희소 행렬이 밀집 행렬로 승격(promoted)된 뒤, 그 뒤의 연산이 다시 희소화(resparsify)하려는 경우예요. 이런 경우는 드물지만 인위적으로 만들 수 있어요. 예를 들어 (fliplr (speye (3)) + speye (3)) - speye (3)은 희소여야 마땅한데 밀집 행렬을 줘요. 일반적으로 이런 경우는 작은 메모리 패널티만 부과해요.
다만 Octave 희소 행렬의 이런 동작이 문제를 일으키는 알려진 경우가 하나 있는데, 바로 diag 함수 처리예요. diag가 희소 행렬을 반환할지 밀집 행렬을 반환할지는 입력 인자의 타입에 따라 달라져요. 그래서
a = diag (sparse ([1,2,3]), -1);
는 희소 행렬을 반환해야 해요. 이것이 실제로 일어나도록 보장하기 위해 sparse 함수와, 그에 기반한 speye 같은 다른 함수들은 표현이 밀집 행렬보다 메모리를 더 쓰더라도 항상 희소 행렬을 반환해요.
더 알아보기
- 희소 행렬의 생성과 활용은 희소 행렬 항목을 참고하세요.
diag,speye,sparse함수의 시그니처도 함께 보면 좋아요.