Ich werde versuchen, meine Erfahrungen aus der Entwicklung von ViennaCL zusammenzufassen, wo wir CUDA- und OpenCL-Backends mit meist 1: 1-Übersetzungen vieler Rechenkerne haben. Aus Ihrer Frage gehe ich auch davon aus, dass wir uns hier hauptsächlich mit GPUs beschäftigen.
Portabilität der Leistung.Erstens gibt es keine leistungsfähigen Kernel in dem Sinne, dass Sie einen Kernel einmal schreiben und er auf jeder Hardware effizient ausgeführt wird. Nicht in OpenCL, wo es aufgrund der breiteren Palette der unterstützten Hardware offensichtlicher ist, sondern auch nicht in CUDA. In CUDA ist dies weniger offensichtlich, da weniger Hardware unterstützt wird, aber auch hier müssen bereits mindestens drei Hardwarearchitekturen (vor Fermi, Fermi, Kepler) unterschieden werden. Diese Leistungsschwankungen können leicht zu einer Leistungsschwankung von 20 Prozent führen, abhängig davon, wie Sie Threads orchestrieren und welche Arbeitsgruppengrößen Sie auswählen, selbst wenn der Kernel so einfach wie eine Pufferkopie ist. Es ist wahrscheinlich auch erwähnenswert, dass es auf GPUs vor Fermi und Fermi möglich war, schnelle Matrix-Matrix-Multiplikationskerne direkt in CUDA zu schreiben. Für die neuesten Kepler-GPUs muss man sich jedoch der PTX-Pseudo-Assemblersprache zuwenden, um der Leistung von CUBLAS nahe zu kommen. Selbst eine vom Hersteller kontrollierte Sprache wie CUDA scheint Probleme zu haben, mit der Hardwareentwicklung Schritt zu halten. Außerdem wird der gesamte CUDA-Code statisch kompiliert, wenn Sie nvcc ausführen, was einen Balanceakt über das -arch-Flag erfordert, während OpenCL-Kernel zur Laufzeit vom Just-in-Time-Compiler kompiliert werden, sodass Sie im Prinzip Kernel anpassen können bis zu den Besonderheiten eines bestimmten Computergeräts. Letzteres ist jedoch ziemlich aufwendig und wird normalerweise erst dann zu einer sehr attraktiven Option, wenn Ihr Code ausgereift ist und wenn Ihre Erfahrung sich ansammelt. Der zu zahlende Preis ist die O (1) -Zeit, die für die Just-in-Time-Kompilierung erforderlich ist. Dies kann in bestimmten Situationen ein Problem sein. OpenCL 2.
Debugging und Profiling. Die CUDA Debugging- und Profiling-Tools sind die besten für GPGPU. AMDs Werkzeuge sind auch nicht schlecht, aber sie enthalten keine Edelsteine wie cuda-gdb oder cuda-memcheck. Auch heute noch bietet NVIDIA die robustesten Treiber und SDKs für GPGPU. Systemabstürze aufgrund fehlerhafter Kernel sind bei OpenCL und CUDA die Ausnahme und nicht die Regel. Aus Gründen, die ich hier wahrscheinlich nicht erläutern muss, bietet NVIDIA das Debugging und Profiling für OpenCL mit CUDA 5.0 und höher nicht mehr an.
Zugänglichkeit und Bequemlichkeit. Es ist viel einfacher, die ersten CUDA-Codes zum Laufen zu bringen, zumal sich CUDA-Code recht gut in den Host-Code integriert. (Der Preis wird später besprochen.) Es gibt viele Tutorials im Internet sowie Optimierungshandbücher und einige Bibliotheken. Mit OpenCL müssen Sie eine Menge Initialisierungscode durchgehen und Ihren Kernel in Strings schreiben, damit Sie nur während der Ausführung Kompilierungsfehler finden, wenn Sie die Quellen an den JIT-Compiler senden. Daher dauert es länger, einen Code- / Kompilierungs- / Debug-Zyklus mit OpenCL zu durchlaufen, sodass Ihre Produktivität in dieser anfänglichen Entwicklungsphase normalerweise geringer ist.
Aspekte der Softwarebibliothek. Während die vorherigen Punkte für CUDA sprachen, ist die Integration in andere Software ein großes Plus für OpenCL. Sie können OpenCL verwenden, indem Sie einfach eine Verknüpfung mit der gemeinsam genutzten OpenCL-Bibliothek herstellen. Bei CUDA müssen Sie jedoch über die gesamte CUDA-Toolchain verfügen. Schlimmer noch, Sie müssen die richtigen Host-Compiler verwenden, damit nvcc funktioniert. Wenn Sie jemals versucht haben, z. B. CUDA 4.2 mit GCC 4.6 oder höher zu verwenden, fällt es Ihnen schwer, die Dinge zum Laufen zu bringen. Wenn Sie zufällig einen Compiler verwenden, der neuer ist als das CUDA SDK, treten in der Regel Probleme auf. Die Integration in Build-Systeme wie CMake bereitet ebenfalls Kopfzerbrechen (zahlreiche Hinweise finden Sie z. B. auf der PETScMailinglisten). Dies ist möglicherweise kein Problem auf Ihrem eigenen Computer, auf dem Sie die volle Kontrolle haben. Sobald Sie jedoch Ihren Code verteilen, werden Sie in Situationen geraten, in denen die Benutzer in ihrem Software-Stack etwas eingeschränkt sind. Mit CUDA können Sie also nicht mehr Ihren bevorzugten Host-Compiler auswählen, sondern NVIDIA legt fest, welche Compiler Sie verwenden dürfen.
Andere Aspekte. CUDA ist etwas näher an Hardware (z. B. Warps), aber meiner Erfahrung mit linearer Algebra nach profitieren Sie davon selten erheblich. Es gibt einige weitere Softwarebibliotheken für CUDA, aber immer mehr Bibliotheken verwenden mehrere Computing-Backends. ViennaCL , VexCL oder Paralution unterstützen alle OpenCL- und CUDA-Backends. Ein ähnlicher Trend ist bei Bibliotheken in anderen Bereichen zu beobachten.
GPGPU ist keine Silberkugel. Es hat sich gezeigt, dass GPGPU eine gute Leistung für strukturierte Operationen und rechenbeschränkte Aufgaben bietet. Bei Algorithmen mit einem nicht zu vernachlässigenden Anteil an der sequentiellen Verarbeitung kann die GPGPU das Amdahl-Gesetz jedoch nicht auf magische Weise überwinden . In solchen Situationen ist es besser, eine gute CPU-Implementierung des besten verfügbaren Algorithmus zu verwenden, als zu versuchen, einen parallelen, aber weniger geeigneten Algorithmus für Ihr Problem zu verwenden. Außerdem ist PCI-Express ein schwerwiegender Engpass. Sie müssen daher im Voraus prüfen, ob die Einsparungen durch GPUs den Mehraufwand beim Hin- und Herbewegen von Daten ausgleichen können.
Meine Empfehlung. Bitte beachten Sie CUDA und OpenCL anstelle von CUDA oderOpenCL. Sie müssen sich nicht unnötig auf eine Plattform beschränken, sondern das Beste aus beiden Welten herausholen. Für mich funktioniert es gut, eine erste Implementierung in CUDA einzurichten, sie zu debuggen, zu profilieren und dann durch einfache Zeichenfolgensubstitutionen nach OpenCL zu portieren Diese Portierung nimmt normalerweise weniger als 10 Prozent Ihrer Zeit in Anspruch, bietet Ihnen jedoch die Möglichkeit, auch auf anderer Hardware zu arbeiten. Sie werden überrascht sein, wie gut Nicht-NVIDIA-Hardware in bestimmten Situationen funktionieren kann. Berücksichtigen Sie vor allem die größtmögliche Wiederverwendung von Funktionen in Bibliotheken. Während eine schnelle & Die fehlerhafte Neuimplementierung einiger Funktionen ist für die Single-Thread-Ausführung auf einer CPU häufig akzeptabel. Sie führt häufig zu einer schlechten Leistung auf einer massiv parallelen Hardware. Im Idealfall können Sie sogar alles in Bibliotheken auslagern und müssen sich nie darum kümmern, ob sie CUDA, OpenCL oder beides intern verwenden. Persönlich würde ich es niemals wagen, herstellergesperrten Code für etwas zu schreiben, auf das ich mich in einigen Jahren verlassen möchte, aber dieser ideologische Aspekt sollte in eine separate Diskussion eingehen.