비엔나 CL 개발 과정에서 얻은 경험을 요약하려고합니다. 여기에는 CUDA와 OpenCL 백엔드가 많은 컴퓨팅 커널을 1 : 1로 번역 한 것이 있습니다. 귀하의 질문에서 우리는 주로 GPU를 사용한다고 가정합니다.
성능 이식성.우선, 커널을 한 번 작성하면 모든 하드웨어에서 효율적으로 실행된다는 점에서 성능이 뛰어난 커널과 같은 것은 없습니다. OpenCL에는 지원되지 않으며 광범위한 하드웨어 지원으로 인해 더 분명하지만 CUDA에는 없습니다. CUDA에서는 지원되는 하드웨어의 범위가 더 작기 때문에 분명하지 않지만 여기서도 적어도 세 가지 하드웨어 아키텍처 (pre-Fermi, Fermi, Kepler)를 구별해야합니다. 커널이 버퍼 사본만큼 단순하더라도 스레드 성능 조정 방법과 선택한 작업 그룹 크기에 따라 이러한 성능 변동으로 인해 20 %의 성능 변동이 쉽게 발생할 수 있습니다. 아마도 페르미 전과 페르미 GPU에서는 CUDA에서 빠른 매트릭스-매트릭스 곱셈 커널을 직접 작성할 수 있었으며, 최신 Kepler GPU의 경우 CUBLAS의 성능에 가까워 지려면 PTX 의사 어셈블리 언어로 내려 가야합니다. 따라서 CUDA와 같은 공급 업체 제어 언어조차도 하드웨어 개발에 보조를 맞추는 데 문제가있는 것으로 보입니다. 또한 nvcc를 실행할 때 모든 CUDA 코드가 정적으로 컴파일됩니다. -arch 플래그를 통해 약간의 밸런싱 동작이 필요하지만 OpenCL 커널은 JIT (Just-In-Time) 컴파일러에서 런타임에 컴파일되므로 원칙적으로 커널을 조정할 수 있습니다 특정 컴퓨팅 장치의 세부 사항까지. 그러나 후자는 매우 복잡하며 일반적으로 코드가 성숙하고 경험이 쌓이면서 매우 매력적인 옵션이됩니다. 지불하는 가격은 JIT (Just-In-Time) 컴파일에 필요한 O (1) 시간이며 특정 상황에서 문제가 될 수 있습니다. OpenCL 2.
디버깅 및 프로파일 링. CUDA 디버깅 및 프로파일 링 도구는 GPGPU에 가장 적합합니다. AMD의 도구도 나쁘지는 않지만 cuda-gdb 또는 cuda-memcheck와 같은 보석은 포함하지 않습니다. 또한 오늘날에도 NVIDIA는 GPGPU를위한 가장 강력한 드라이버와 SDK를 제공합니다. 버그가 많은 커널로 인한 시스템 정지는 OpenCL과 CUDA의 규칙이 아니라 예외입니다. 여기서 설명 할 필요가 없기 때문에 NVIDIA는 더 이상 CUDA 5.0 이상의 OpenCL에 대한 디버깅 및 프로파일 링을 제공하지 않습니다.
접근성과 편의성. CUDA 코드가 호스트 코드와 다소 잘 통합되기 때문에 첫 번째 CUDA 코드를 시작하고 실행하는 것이 훨씬 쉽습니다. (나중에 지불 할 가격에 대해 논의하겠습니다.) 웹에는 최적화 안내서 및 일부 라이브러리뿐만 아니라 많은 자습서가 있습니다. OpenCL을 사용하면 약간의 초기화 코드를 거쳐 커널을 문자열로 작성해야하므로 소스를 jit-compiler에 공급할 때 실행 중에 컴파일 오류 만 찾을 수 있습니다. 따라서 OpenCL을 사용하여 하나의 코드 / 컴파일 / 디버그주기를 수행하는 데 시간이 오래 걸리므로 초기 개발 단계에서 생산성이 저하됩니다.
소프트웨어 라이브러리 측면. 이전 항목은 CUDA를 선호했지만 다른 소프트웨어와의 통합은 OpenCL의 큰 장점입니다. 공유 OpenCL 라이브러리와 연결하기 만하면 OpenCL을 사용할 수 있습니다. CUDA에서는 전체 CUDA 툴체인을 사용할 수 있어야합니다. 더 나쁜 것은, nvcc가 작동하려면 올바른 호스트 컴파일러를 사용해야합니다. 예를 들어 CUDA 4.2를 GCC 4.6 이상과 함께 사용하려고 시도하면 작업을 수행하는 데 어려움을 겪을 수 있습니다. 일반적으로 CUDA SDK보다 새로운 컴파일러를 사용하면 문제가 발생할 수 있습니다. CMake와 같은 빌드 시스템으로의 통합은 두통의 또 다른 원인입니다 (예 : PETSc 에서 충분한 증거를 찾을 수 있습니다)메일 링리스트). 이것은 완전히 제어 할 수있는 컴퓨터에서는 문제가되지 않지만 코드를 배포하자마자 소프트웨어 스택에서 사용자가 다소 제한되는 상황에 처하게됩니다. 다시 말해 CUDA를 사용하면 더 이상 좋아하는 호스트 컴파일러를 자유롭게 선택할 수 없지만 NVIDIA는 사용할 수있는 컴파일러를 지정합니다.
다른 측면. CUDA는 하드웨어에 약간 더 가깝지만 (예 : 워프) 선형 대수학에 대한 나의 경험은 거의 대수를 얻지 못한다는 것입니다. CUDA를위한 소프트웨어 라이브러리가 몇 개 더 있지만, 점점 더 많은 라이브러리가 여러 컴퓨팅 백엔드를 사용합니다. ViennaCL , VexCL 또는 Paralution은 모두 OpenCL 및 CUDA 백엔드를 지원하지만 다른 영역의 라이브러리에서도 비슷한 추세를 볼 수 있습니다.
GPGPU는은 총알이 아닙니다. GPGPU는 구조화 된 작업 및 컴퓨팅 제한 작업에 우수한 성능을 제공하는 것으로 나타났습니다. 그러나 무시할 수없는 순차 처리 알고리즘을 가진 알고리즘의 경우 GPGPU는 암달의 법칙을 마술처럼 극복 할 수 없습니다 . 이러한 상황에서는 병렬 처리를 시도하는 대신 사용 가능한 최상의 알고리즘을 CPU로 구현하는 것이 좋습니다. 또한 PCI-Express는 심각한 병목 현상이므로 GPU의 절감 효과로 데이터 이동의 오버 헤드를 보상 할 수 있는지 여부를 미리 확인해야합니다.
내 추천. CUDA 또는 CUDA 대신 CUDA 및 OpenCL을 고려하십시오.OpenCL. 불필요하게 자신을 하나의 플랫폼으로 제한 할 필요는 없지만, 대신 두 세계를 최대한 활용하십시오. 나를 위해 잘 작동하는 것은 CUDA에서 초기 구현을 설정하고 디버깅하고 프로파일 링 한 다음 간단한 문자열 대체로 OpenCL로 포팅하는 것입니다. 이러한 이식 노력은 일반적으로 시간의 10 % 미만을 소비하지만 다른 하드웨어에서도 실행할 수 있습니다. 특정 상황에서 NVIDIA 이외의 하드웨어가 얼마나 잘 작동하는지 놀랄 수 있습니다. 무엇보다도 라이브러리에서 기능을 최대한 재사용하는 것을 고려하십시오. 빠른 동안 & 일부 기능의 불완전한 재 구현은 종종 CPU에서 단일 스레드 실행에 적합하며 대규모 병렬 하드웨어에서 성능이 저하되는 경우가 많습니다. 이상적으로 모든 것을 라이브러리로 오프로드 할 수 있으며 CUDA, OpenCL 또는 내부적으로 둘 다 사용하는지 신경 쓰지 않아도됩니다. 개인적으로 나는 앞으로 몇 년 동안 내가 의존하고 싶은 것에 대해 벤더 잠금 코드를 작성하는 것을 결코 감히하지 않을 것이지만,이 이념적 측면은 별도의 논의로 넘어 가야한다.