계산을 행렬 곱셈으로 표현하는 것이 더 빠른 이유는 무엇입니까?


18

TensorFlow를 사용하는 Google MNist 튜토리얼 에서 한 단계가 행렬에 벡터를 곱하는 것과 동등한 계산이 표시됩니다. Google은 먼저 계산을 수행하는 데 필요한 각 숫자 곱셈과 덧셈이 전체로 작성된 그림을 보여줍니다. 다음으로,이 버전의 계산이 더 빠르거나 적어도 더 빠를 수 있다고 주장하면서 행렬 곱셈으로 표현 된 그림을 보여줍니다.

그것을 방정식으로 쓰면 다음과 같이됩니다.

스칼라 방정식

이 절차를 "벡터화"하여 행렬 곱셈과 벡터 덧셈으로 바꿀 수 있습니다. 이것은 계산 효율성에 도움이됩니다. (생각하는 유용한 방법이기도합니다.)

벡터 방정식

나는 이와 같은 방정식이 일반적으로 기계 학습 실무자에 의해 행렬 곱셈 형식으로 작성되며 물론 코드 간결성 또는 수학 이해의 관점에서 그렇게하는 이점을 볼 수 있음을 알고 있습니다. 내가 이해하지 못하는 것은 긴 형식에서 행렬 형식으로 변환하는 것이 "계산 효율에 도움이 된다 "는 Google의 주장입니다

계산을 행렬 곱셈으로 표현하여 소프트웨어의 성능 향상을 언제, 왜, 어떻게 얻을 수 있습니까? 인간으로서 두 번째 (행렬 기반) 이미지에서 행렬 곱셈을 계산하려면 첫 번째 (스칼라) 이미지에 표시된 각 개별 계산을 순차적으로 수행하여 수행합니다. 나에게, 그들은 동일한 계산 순서에 대한 두 가지 표기법에 지나지 않습니다. 컴퓨터와 다른 이유는 무엇입니까? 컴퓨터가 스칼라보다 행렬 계산을 더 빨리 수행 할 수있는 이유는 무엇입니까?

답변:


19

이것은 명백한 들릴지 모르지만, 컴퓨터가 실행되지 않는 공식을 , 그들이 실행 코드를 , 얼마나 오랫동안 실행이 소요 그들이 어떤 개념이 코드 구현에 간접적으로 만 실행하고 코드에 직접 의존한다. 논리적으로 동일한 두 코드 조각은 매우 다른 성능 특성을 가질 수 있습니다. 특히 행렬 곱셈에서 발생할 수있는 몇 가지 이유는 다음과 같습니다.

  • 여러 스레드를 사용합니다. 여러 개의 코어가없는 최신 CPU는 거의 없으며, 최대 8 개까지 보유하고 있으며, 고성능 컴퓨팅을위한 특수 머신은 여러 소켓에서 64 개를 쉽게 가질 수 있습니다. 일반적인 프로그래밍 언어에서 명백한 방식으로 코드를 작성하면 그 중 하나만 사용합니다 . 다시 말해, 실행중인 컴퓨터의 사용 가능한 컴퓨팅 리소스 중 2 % 미만을 사용할 수 있습니다.
  • SIMD 명령어 사용 (혼란스럽게도 "벡터화"라고하지만 질문의 텍스트 인용 부호와는 다른 의미로 사용됩니다). 본질적으로 4 또는 8 정도의 스칼라 산술 명령어 대신 CPU 에 4 또는 8 정도의 레지스터에서 병렬로 산술을 수행하는 하나의 명령어를 제공하십시오 . 이것은 문자 그대로 약간의 계산을 할 수 있습니다 (완전히 독립적이며 명령 세트에 적합 할 때) 4 또는 8 배 빠릅니다.
  • 더 똑똑한 캐시 사용 . 메모리 액세스는 시간적으로 공간적으로 일관성 이있는 경우 더 빠릅니다 . 즉, 연속적인 액세스는 근처의 주소에 대한 것이고, 주소에 두 번 액세스 할 때는 오래 멈추지 않고 빠르게 두 번 연속해서 액세스합니다.
  • GPU와 같은 가속기를 사용합니다. 이 장치는 CPU와는 매우 다른 야수이며 효율적으로 프로그래밍하는 것은 그 자체의 예술적 형태입니다. 예를 들어 수십 개의 코어가 수십 개의 코어 그룹으로 그룹화되어 있으며이 그룹은 리소스를 공유합니다. 일반 메모리보다 훨씬 빠른 몇 KiB의 메모리를 공유하며 그룹의 코어가 if그 그룹의 다른 모든 사람들이 그것을 기다려야한다고 진술하십시오.
  • 엄청난 수의 새로운 두통을 유발하지만 물론 훨씬 더 큰 컴퓨팅 리소스에 액세스 할 수있는 여러 컴퓨터 (수퍼 컴퓨터에서 매우 중요)에 작업분산시킵니다 .
  • 똑똑한 알고리즘. 행렬 곱셈의 경우 위의 트릭으로 적절하게 최적화 된 간단한 O (n ^ 3) 알고리즘은 종종 적절한 행렬 크기를 위해 하위 입방체 보다 빠르지 만 때로는 이기게됩니다. 희소 행렬과 같은 특수한 경우 특수 알고리즘을 작성할 수 있습니다.

많은 똑똑한 사람들이 위의 트릭을 사용하고 일반적으로 어리석은 플랫폼 별 트릭을 사용하여 일반적인 선형 대수 연산을 위해 매우 효율적인 코드를 작성했습니다 . 따라서 수식을 행렬 곱셈으로 변환 한 다음 성숙한 선형 대수 라이브러리를 호출하여 계산을 구현하면 해당 최적화 노력의 이점이 있습니다. 반대로, 고급 언어로 공식을 명백하게 작성하면 결국 생성되는 머신 코드는 이러한 트릭을 모두 사용하지 않으며 그리 빠르지 않습니다. 이것은 매트릭스 공식을 취하고 자신이 작성한 순진한 행렬 곱셈 루틴을 호출하여 구현하는 경우에도 마찬가지입니다 (명확한 방식으로).

만들기 코드는 빠른 작업 소요 성능의 마지막 온스를 원하는 경우 작업을 꽤 많이, 자주. 많은 중요한 계산이 두 개의 선형 대수 연산의 조합으로 표현 될 수 있기 때문에 이러한 연산에 대해 고도로 최적화 된 코드를 작성하는 것이 경제적입니다. 하지만 일회용 일회성 유스 케이스? 아무도 당신을 제외하고는 신경 쓰지 않으므로 그것을 최적화하는 것은 경제적이지 않습니다.


4

(스파 스) 행렬-벡터 곱셈은 병렬화가 가능합니다. 데이터가 크고 서버 팜을 사용할 수 있으면 매우 편리합니다.

이것은 행렬과 벡터를 덩어리로 나누고 별도의 기계가 일부 작업을 수행하게 할 수 있음을 의미합니다. 그런 다음 일부 결과를 서로 공유 한 다음 최종 결과를 얻습니다.

귀하의 예에서 작업은 다음과 같습니다.

  1. 그리드의 좌표에 따라 각각 Wx, y를 유지하는 프로세서 그리드 설정

  2. 각 열을 따라 소스 벡터 브로드 캐스트 (비용 O(log height))

  3. 각 프로세서를 곱셈에 로컬로 (비용 O(width of submatrix * heightof submatrix))

  4. 합계 (비용 O(log width))를 사용하여 각 행을 따라 결과 축소

이 마지막 연산은 합이 연관되어 있으므로 유효합니다.

또한 이중화로 구축 할 수 있으며 모든 정보를 단일 시스템에 넣지 않아도됩니다.

그래픽에서 볼 수 있듯이 작은 4x4 매트릭스의 경우 CPU에 이러한 명령을 처리하기위한 특수 명령 및 레지스터가 있기 때문입니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.