[GM] 4. 행렬
4.행렬
4.1 행렬의 정의
4.1.1 정의
- 행렬(matrix): 행(row)과 열(column)이 있는 격자모양 배열 안에 스칼라를 나열한 것
- 요소(element): 행렬 안에 나열된 스칼라
- 대각 요소(diagonal element): 행렬요소 mij에 대해 i=j인 요소
4.1.2 행렬의 종류
- 정사각행렬(square matrix): 행과 열의 수가 같은 행렬
- 대각행렬(diagonal matrix): 정사각행렬이고 대각 요소 이외의 요소가 모두 0인 행렬
- 단위행렬(identity matrix): 대각요소가 모두 1인 대각행렬
- 영행렬(zero/null matrix): 모든 성분이 0인 행렬
- 열벡터와 행백터는 벡터로서는 같음, 행렬로서는 다름
4.2 행렬의 연산
4.2.1 행렬과 행렬의 연산
- 유니티 Matrix4x4 클래스는 행렬 곱 계산만 지원
- 행렬의 곱셈은 A의 열수와 B의 행수가 같은 경우만 정의 됨
- M=AB의 요소 eij는 다음과 같이 정의
- 행렬의 곱은 각각의 행벡터와 열벡터의 내적이 되는 형식으로 나타낼 수 있음
- 교환법칙X, 결합법칙O
- 단위행렬은 다른 행렬과 곱해도 곱해진 행렬이 변화하지 않는다는 특별한 성질 만족
AI = IA = A
4.2.2 전치행렬
- 전치행렬(transpose): M의 mij와 mji를 바꿔넣은 행렬 M^T
- M이 대각행렬인 경우 M^T=M
- (M^T)^T = M
- (MN)^T = N^T M^T
- 행벡터와 열벡터를 서로를 전치한 것
- 열벡터 v와 열벡터 w의 내적을 행렬끼리의 곱 v^T w로 표현가능
4.2.3 역행렬
- 역행렬(inverse): MM^-1 = M^-1 M = I
- 정사각행렬로만 구할 수 있음
- 단위행렬 I의 역행렬의 자기 자신
- 가역행렬(invertible~) / 정칙행렬(regular~): 역행렬이 존재하는 행렬
- (M^-1)^-1 = M
- (MN)^-1 = N^-1 M^-1
- (M^T)^-1 = (M^-1)^T
4.2.4 행렬과 벡터의 곱셈
- (vM)^T = M^T v^T
- (u+v)M = uM + vM
- (((vM)N)P)^T = P^T (N^T (M^T v^T))
4.2.5 스위즐 연산
- 스위즐(swizzle) 연산: 행렬과 벡터의 곱으로 벡터의 성분을 변경하는 연산
- 부울 행렬(boolean matrix): 0과 1요소만으로 구성된 행렬
- 산포 스위즐(broadcast swizzle): 성분 중 하나를 벡터 전체에 벌여놓는 스위즐 연산
- 벡터 연산을 위해 CPU에 내장된 SIMD (single instruction multiple data) 명령 세트와
GPU 프로그래밍을 위한 셰이딩 언어에 구현된 경우가 많음
4.2.6 행우선과 열우선
- 행우선(row major) 방식: 행렬의 1행씩 1차원 배열에 채워짐
- 열우선(column major) 방식: 1열씩 1차원 배열에 채워짐
- Unity의 matrix4x4는 열우선
- C/C++은 행우선
- Mv에서 M의 각 행과 v와의 내적으로 Mv의 각 성분을 구한 경우 M의 각 행에 엑세스가 발생하므로 행우선이 유리
- Mv를 M과 v^T 산포 스위즐 연산의 아다마르 곱(Hadamard product)으로 구하면
Mv = v1^T c1 + v2^T c2 + ... + vn^T cn
이 방법을 사용할 때는 열우선이 유리
4.2.7 AoS와 SoA
- AoS(Array of Structures), SoA(Structure of Array)
- 멤버 변수 x, y, z, w를 가진 구조체 4개가 있다고 했을 때
- 구조체의 배열(AoS): 행우선으로 처리하면 x0, y0, z0, w0이라는
4가지 다른 종류의 데이터를 가진 구조체를 요소로 하는 배열의 요소를 차례로 처리해나가게 됨
벡터 연산을 적용하려면 처리 커널이 분산된 메모리 주소를
읽기/쓰기(gather/scatter) 해야 하므로 메모리에 랜덤하게 엑세스함
처리를 요청하고 나서 결과가 돌아오기까지의 레이턴시(latency)가 늘어나 성능저하
CPU에 구현된 SIMD 연산명령 때문에 메모리 패딩과 얼라인먼트 조정이 필요하므로 불필요한 공간 발생가능
- 배열의 구조체(SoA): 열우선으로 처리하면 x0, x1, x2, x3 처럼 배열/벡터로서
각 성분에 같은 연산을 적용하여 일괄 처리하므로 그 배열을 멤버로서 여러 개 묶은 구조체를 전체로 봄
그리고 구조체의 각 멤버를 차례로 처리
최근 CPU는 스트림 프로세싱 기법으로 대량의 데이터를 처리하기 위해
1명령으로 복수의 같은 종류 데이터(벡터)를 처리하는 SIMD 명령 구현
단 SoA데이터에 랜덤 엑세스가 많이 발생하면 같은 캐시 라인에 관련 데이터를 두기 어려워
공간적 소속성이 낮아지며 캐시스래싱이 일어나기 쉬워져 성능 저하
- 캐시스래싱(cache thrashing): 캐시 내용의 교체가 빈번히 일어나 캐시를 사이에 두는 의미가 손상되는 것
4.2.8 행렬식
- 행렬식(determinant): 행렬을 수식으로 간주해 스칼라 값을 얻는 것
정사각행렬만 정의
- det(A) 또는 | A |로 표기
- 두 행 또는 열을 교환하면 부호 반전
- 어떤 행 또는 열을 상수배하면 행렬식이 같은 상수배 됨(다중선형성)
- | I | = 1
- |A^T| = |A|
- |A^-1| = 1/|A| = |A|^-1
- |A| |B| = |AB|
- 여인수(cofactor)전개: 임의의 정사각생렬의 행렬식을 구하는 식
- 소행렬식(minor) Mij: n x n 행렬 A에서 i행과 j열을 제거한 (n-1) x (n-1) 행렬의 행렬식
- 여인수 Cij: (-1)^(i+j) Mij
- 여인수를 이용한 A의 행렬식
i와 j는 어떤 행이나 열을 선택해도 결과가 바뀌지 않음
- 2, 3차원 정사각행렬은 미리 식을 준비하는 것이 좋음
- 행렬식의 기하학적 의미
2 x 2 행렬식: (0,0), (a,b), (c,d), (a+c,b+d)를 정점으로 하는 평행사변형의 면적
3 x 3 행렬식: 스칼라 삼중적(scalar triple product): a · (b x c)
- 스칼라 삼중적 vs 벡터 삼중적: 스칼라 삼중적은 벡터 a, b, c를 어느 순서로 끼워넣든 값이 변하지 않음
a · (b x c) = b · (c x a) = c · (a x b)
- 행렬식으로 얻는 것은 부포가 있는 체적이고, 유사벡터처럼 좌표계에 따라 부포를 바꾸므로
유사스칼라(pseudo scalar)로 불림
- a,b,c가 선형종속인지 행렬식=0 여부로 판별 가눙
4.2.9 직교행렬
- 직교행렬(orthogonal matrix): 자신과 전치행렬의 곱이 I인 행렬
M^T M = M M^T = I
M^T = M^-1
- 즉 직교행렬을 단순히 전치하면 역행렬을 얻을 수 있음
- 어느 열벡터/행벡터를 두 개 추출하더라도 두 내적은 0(=직교한다)
- |M^T M| = |M|^2 = 1
즉 |M| = 1 또는 -1
- 특수직교행렬(special orthogonal matrix): 행렬식이 1이 되는 직교행렬
어떤 행과 열도 정규화된 크기 1인 단위벡터로서 다룰 수 있음
또한 행끼리, 열끼리는 수직
- 서로 수직인 단위벡터라는 의미에서 특수직교행렬의 각 행과 열은 정규직교기저(orthogonal basis)라 불림
정규직교기저는 직교좌표계의 기저