Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

93
Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing 5. Mai 2014 Jörn Dinkla Version 1.0

Transcript of Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Page 1: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Tipps & Tricks für den erfolgreichen

Einsatz von GPU-Computing

5. Mai 2014

Jörn Dinkla

Version 1.0

Page 2: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Motivation

Page 3: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Angekündigt „In diesem Vortrag wird ein sequenzielles

Programm schrittweise in ein optimiertes massiv-paralleles GPU-Programm überführt…“

Aber CUDA 6.0

Optimierungsergebnisse Kepler

Didaktisch nicht geeignet Zu viel Fachlogik, zu wenig GPU

Daher mehrere kleine Programme, aber mehr GPU

Klärung

Page 4: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Folien und Sourcecode gibt es

unter ...

http://dinkla.net/parallel2014

Download

Page 5: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Tablet, PC, Großrechner, Cloud,

Spielkonsole, Autos …

GPU-Computing überall

Page 6: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Vom Modell zum Bild ...

Computer-Grafik

Tomas Akenine-Mőller © 2002, Quelle: http://www.realtimerendering.com/

Page 7: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Programmierbare Shader

Page 8: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Massiv Parallel

Page 9: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Kepler GK 110

Page 10: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Z. B. NVIDIA Tesla

AMD FirePro

Eigenschaften ECC Speicher

Größerer Speicher

Bessere Double-Performance

Kein Monitor-Anschluss

Keine Kühlung

Auch spezielle Karten

Page 11: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

C ++ 11

C ++

C

Frameworks

Device

WDDM

FrameworkCUDA

OpenCL

C++

AMP

DirectX

AMDTreiber TDD

Thrust C++-

Wrapper

Library

Page 12: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

CUDA⊖ Benötigt NVIDIA-Hardware

⊕ Teilweise C++

⊕ Am meisten benutzt

C++ AMP⊖ Benötigt Windows/DirectX, Einschränkungen

⊖ Noch „jung“, keine erprobten Libraries

⊕ C++ 11

OpenCL⊖ Geringer Abstraktionsgrad, C99

⊖ Nicht so viele Libraries wie bei CUDA

⊕ Apple, Intel, AMD

Einschränkungen

Page 13: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Schnelle erste Erfolge

2x – 5x Speedup

Dann wird es schwieriger …

Wissen über die Hardware

notwendig

Speedup

2 3 4 5 6 7 8 9 10 11 …

Page 14: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Schneller, Größer, Besser

Nur wenn notwendig!

Parallelisieren?

1080p Ultra HD / 4K720p576p480p

Page 15: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Nicht das Rad neu erfinden

„best practices“

„think parallel“

Empfehlung:

„Structured Parallel Programming“

Michael McCool et. al.

Intel-lastig, Cilk Plus, TBB

Parallele Patterns

Page 16: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Parallele Patterns

Siehe http://www.parallelbook.com/

Page 17: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

map (*2) [1..1024] = [2,4,…,2048]

Datenparallelität: Map

Index 0 1 2 3 4 5 6 7 … 1023

Wert 1 2 3 4 5 6 7 8 … 1024

Ergebnis 2 4 6 8 10 12 14 16 … 2048

Page 18: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Mit Thrust

Page 19: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Mit C++ AMP

Lambda-Ausdruck:

[bindings](params) {

body; }

Page 20: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Bolt

Ähnlicher Abstraktionsgrad

Leider nur für AMD

Projekt nicht aktiv

C++-Bindings

C++ (Nicht C++ 11)

Siehe „Schneller Einstieg in OpenCLmit C++-Bindings“

OpenCL

Page 21: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Abstraktion wichtig für Fortschritt

Java, JVM, Web-Frameworks mit Ruby

Rapid Prototyping

Aber:

Hintergrundwissen bei GPU-Computing notwendig!!!

Was ist hinter dem „Vorhang“ des APIs?

Die beiden Programme haben einen Unterschied! Wer findet ihn?

Schöne neue Welt

Page 22: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

De

vic

e

Kernel

sequenced

Kernel

transform

Ho

st

d‘

d d

De

vic

e

Kernel

transform

Ho

st

v

av av

v iota v

Beispiel mit thrust (konstruiert, muss nicht so sein!)

Beispiel mit C++ AMP (konstruiert, muss nicht so sein!)

Page 23: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Host

Host und Device

CPU 1

Core

Global Memory

Bus

GPU / Device

Mem. Ctrl.

Prozessor (SM)

C CC C

C CC C

C CC C

Core

Core Core

Global Memory

8/16

Page 24: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Host und Device

Host

Der „Kopf“ des Ganzen

Management Speicher, Queues, Events

Aufruf von Kerneln

Synchronisation

Device

Traditionell „reine Arbeitspferde“

Page 25: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Basis: BaseBuffer

HostBuffer

Unpinned

Pinned (nicht swapbar)

Lokaler Speicher (NUMA)

DeviceBuffer

Buffer

Page 26: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Host- und Device-Buffer

Versionierung der beiden Seiten

get_host()->incr_version()

Aktualisierung je nach Version

update_host()

update_device()

CUDA 6: Unified Memory

BufferPair

Ho

st

Buffer

De

vic

e

Buffer

Page 27: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

1. Übergebe ID als Parameter

2. Hole Daten anhand ID

3. Verarbeitung

4. Speichere Daten anhand ID

SPMD / SIMT

Page 28: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Kernel ruft Funktion op auf

Index-Berechnungen extern

Back to the Basics

Page 29: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Größe / Extension

width, height, depth

index(x,y,z)

in_bounds(x,y,z)

int checked_index(x,y,z)

Extent

0 1 2 3

0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

1

2

3

Page 30: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Grund: Kernel in der Praxis

Aus Wilt „The CUDA Handbook“, S. 218

„Index-

Schlacht“

OptimiertNachteil: Speicherorganisation

fest verdrahtet

Page 31: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Vor dem Kernel-Aufruf Wechsel der Abstraktionsebene

Host zu Device

Von C++-Datenstrukturen zu Device-Pointern

Aufruf des Kernels

Kernel-Aufruf

Page 32: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Größe des Thread-Block Für Performance wichtig

Hängt von Hardware ab

Zerlegung der Eingabedaten Thread-Block, Work group, Tile

Grid, NDRange

Beispiel Daten 8x8

Grid 2x2

Block 4x4

NestedExtent

Grid = Data/Block

0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7

0

1

2

3

4

5

6

7

0 1

2 3

Daten, Pixel, Voxel Grid

Page 33: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

kernel<<<g, tb, sm, s>>>(params)

Kernel-Konfiguration

dim3 Grid g

dim3 Thread-Block tb

Größe des Shared-Memory sm

cudaStream_t s

Oft abhängig vom Extent

CudaExecConfig(Extent& e)

CudaExecConfig

Page 34: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Benchmark mit folgenden Funktor

und verschieden Block-Größen

Blockgröße und Performance

Page 35: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Magische 32! Optimum 128?

Warum?

Unterschiedlichen Laufzeiten

Anzahl Threads Zeit [ms]

1 686,449

2 333,055

3 222,076

4 166,660

5 133,771

16 42,532

32 21,878

64 12,491

96 9,269

128 8,306

192 8,937

256 8,617

512 8,476

768 10,123

1024 8,563

Page 36: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Ein Thread-Block wird einem

festen SM zugewiesen

Zerlegung eines Blocks in Warps

32 Threads pro Warp

Kleinste Scheduling-Einheit

Thread-Block-Größe

Vielfaches von 32

Grund: Warp

Page 37: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

CUDA Nsight (Visual Studio, Eclipse)

Visual Profiler (Eclipse)

Kommandozeile nvprof

OpenCL Intel Vtune (*)

AMD CodeXL

C++ AMP Visual Studio 2013

Profiling

Page 38: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Computation Bound

Alle Prozessoren 100% ausgelastet

Memory Bound

Bandbreite zum Speicher voll

ausgelastet

Latency Bound

Warten auf die Daten

Arten der Auslastung

Page 39: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Sortiert nach Optimierungspotential

NVVP‘s Guided Analysis

Hier!

Page 40: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Memory Bound

Page 41: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Host

Verschiedene Speicher

CPU 1

Core

L1 / L2

Core

L1 / L2

L3 Cache

Global Memory

Bus

GPU

Global Memory

Constant Texture

Prozessor (SM)

Local / Shared / L1

Registers

C CC C

L2 Cache

8/168-20

192/

288

1600

8000

Mem. Ctrl.

Page 42: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

128 Kerne sind Optimum

Page 43: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Einfaches Beispiel,

überraschendes Ergebnis

128 Optimum, aber 192 Kerne

„Viel hilft viel“ stimmt hier nicht

Kernel-Konfiguration

Anzahl der Threads = 32*k

Benchmarks notwendig!

Fazit

Page 44: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Lesezugriffe und Schreibzugriffe Anzahl, Datenmenge, Zugriffsmuster

Operationen Komplexität pro Element / Granularität

O(1)

O(log n)

O(n)

O(n^2)

In der Regel memory bound aber evtl. computation bound

Performance einer Map

Page 45: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Mandelbrot-Kernel

Page 46: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

BenchmarkThread-Block Laufzeit [ms]

32, 4 2444,86

64, 4 2453,58

32, 6 2453,65

64, 2 2457,14

32, 5 2465,33

192, 2 2469,59

128, 1 2476,28

64, 3 2479,65

96, 3 2480,85

Page 47: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Occupancy

Unterschiede? Profilen!

Limiter!

Page 48: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Max. 16 Thread-Blöcke „resident“ (*)

Einer aktiv (dunkelgrün)

Ready to go (hellgrün)

Wartend auf Speicher (orange)

Z. B. Occupancy 5/8 = 62.5%

Latency Hiding

W0SMX W1 W2 W3 W4 -- -- --

Page 49: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Berücksichtige (Werte für CC 3.5) Max Threads pro Block 1024

Max Blocks pro SMX 16

Max Warps pro SMX 64

Max Threads pro SMX 2048

Anzahl 32-bit Register pro SMX 64K

Max Anzahl Register pro Thread 255

Max Shared Mem pro SMX 48 KB

Max Shared Mem pro Block 48 KB

Occupancy ist komplex

Page 50: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Occupancy Calculator

Page 51: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

128 Threads pro Block

16 Thread-Blöcke pro SMX

2048 Threads pro SMX

192 Threads pro Block

Passen nur 10 TB / SMX

Insg. 1920 Threads pro SMX

Denn 11*192 = 2112 > 2048

128 besser als 192

Page 52: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Computation bound

Guided Analysis

Page 53: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

1204,75 GFLOPS

Erreichte Performance

Page 54: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Inhärent sequentiell wg. while

Weitere Optimierung?

Page 55: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

ABER:

Laut Werbung: 3977 GFLOPS (GTX 780)

Volle Auslastung einer GPU

Alle Kerne auf allen SMX bearbeiten eine FMA, d.h. warten nicht auf den Speicher

FLOPS = Anzahl der Kerne * Takt * 2

780er: 2304 * 863 Mhz * 2

FMA („Fused multiply-add“) zählt als zwei Operationen

Theoretisches Maximum

Page 56: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Schleifen

Integer-Berechnungen

Speicher-Zugriffe

„Instruktions-Mix“

… schwer zu erreichen

Page 57: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Vergleich 5k*5k, 1000 MaxIter

ProzessorIntel Core i7

3820 3.7 GHz

Intel Core i7

4960HQ

2.60GHz

EVGA 780, 967

MHz Base, 1020

MHz Boost

Laufzeit [ms] 24.249 20.784 39,605

Faktoren Faktoren Faktoren

1 Kern 612,271 524,782 1,000

4 Kerne 153,068 131,196

8 Kerne 76,534 65,598

12 Kerne 51,023 43,732

16 Kerne 38,267 32,799

Vergleich mit CPUs

Page 58: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Kopie zum Device?

Pro Node eine Kopie? Performance?

Hierarchische Datenstrukturen

Page 59: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Möglichkeit

Eigene Speicherverwaltung

Ein Array

new überladen

int index

Statt Pointer

Eine Kopie

Hierarchische Datenstrukturen

Page 60: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

cudaMallocManaged()

Page 61: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Suche nach 1…7 in Baum

Parallele Baumsuche

4

2 6

7531

Page 62: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Parallele Baumsuche

Page 63: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Single Instruction!!!

Mask-Bit für jeden Thread im Warp

SIMT - Divergenz

0 1 2 3

int tid = treadIdx.x;

if (tid < 2) {

call_expensive_function()

} else {

call_expensive_function2()

}

Warps Code

Page 64: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Divergenz

Divergenz

Page 65: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

While-Schleife statt Rekursion

Keine Divergenz mehr!

Verbesserung

Page 66: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

„Dynamic Parallelism“

Ab CC 3.5, CUDA 5.5

Rekursive Kernel

Page 67: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Einschränkungen

Stack-Frames benötigen

Speicherplatz

Rekursionstiefe beschränkt

Rekursive Kernel

Page 68: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Wenig Elemente

„Sparse“ Daten

0 1 2 3 4 5 6 7

0

1

2

3

Divergenz

Page 69: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Komprimieren!

Daten liegen „dicht“

„Keine“ Divergenz mehr!

Minimierung von Kopien!

Pack / Expand

0 1 2 3 4 5 6 7 0 1 0 1

0 0

1 1 1 5

2 2 3 6

3 3 1 2

Page 70: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Maximiere in dieser Reihenfolge

1. Parallelität

2. Speicherdurchsatz

3. Berechnungsdurchsatz

Anleitung: Optimierung

Page 71: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Maximiere Parallelität

Kerne

CPUs

GPUs

SMXs

Kerne

Page 72: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Wegen Kopien

Auf dem Device behalten?

Auslastung gering

Page 73: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Überlappung: Kopie und Kernel

Möglichkeit: Streaming

Page 74: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Kopien müssen asynchron sein

cudaMemcpyAsync(…,stream)

Kernel bekommen Argument

kernel<<<g, b, sm, stream>>>(…)

Synchronisation

Nur, wenn notwendig

cudaStreamSynchronize

Streaming

Page 75: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Aufwand

Umstellen des Codes

Einfügungsreihenfolge

HyperQ ab CC 3.5

Bei CC<3.5 Achtung Performance

Auf richtige Reihenfolge achten

Siehe Literatur

Synchronisation über Events

Streaming

Page 76: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Einsatz mehrerer GPUs

Explizite Auswahl des Devices

CUDA: cudaSetDevice()

OpenCL: clCreateContext()

C++ AMP: accelerator_view als

Argument zu parallel_for_each

Multi-GPU

Page 77: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Kernel und Speicher auf gleichem Device!

=> Partionierung / Strategie

Datenstruktur für Zuordnung

map<partition, device>

Vorsicht bei Bibliotheken

Z. B. Thrust

Bisher nicht komfortabel gelöst

Anforderungen

Page 78: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Multi-GPU

Page 79: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Steuerung durch den Host

Möglichkeiten

1. Ein Thread füllt alle Streams

2. Pro GPU ein Thread für zwei

Streams

3. Pro Stream ein Thread

Performance ist systemabhängig

Multi-GPU

Page 80: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

OpenMP

Warte

OpenMP

Page 81: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

CPUs nutzen

Auslastung der GPU Parallele Kernel

Streams

Auslastung der SMs Thread-Block

Occupancy

Auslastung der Kerne „Instruction level parallelism“ (ILP)

Maximiere Parallelität

Page 82: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Minimiere Synchronisation

Innerhalb Thread-Block

__syncthreads()

Atomare Zugriffe

atomicAdd()

Speicher

Zwischen Kernel-Aufrufen

Maximiere Parallelität

Page 83: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

On-Chip-Speicher

Register, Shared/Local

Cache

Spezial-Speicher

Konstanter Speicher, Texturspeicher

Device-Speicher

Minimiere Kopien

„Coalesced“ Transaktionen

Max. Speicherdurchsatz

Page 84: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Transaktionen sind immer 32, 64

oder 128 Byte

Innerhalb eines Warps

„Zusammengefasst“

„Coalesced“

Speicherdurchsatz

31 63 95 127 159 191 223 255 287 319 351 383

Page 85: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

y- statt x-Richtung

Speicherdurchsatz

31 63 95 127 159 191 223 255 287 319 351 383

Page 86: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Minimiere Divergenz

Loop-Unrolling

Berechnen statt Speichern

Arithmetik –fast_math

Präzision vs. Geschwindigkeit

Fusion von Kerneln

Max. Berechnungen

Page 87: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Heuristiken, keine Patentrezepte

Bisher Unterschiede bei jeder

Karten-Generation

Benchmarks sind Pflicht!

Neugierde auch!

Literatur ist inzwischen reichlich

vorhanden

Fazit

Page 88: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Einsteiger

„CUDA by Example“ Sanders, Kandrot

Fortgeschritten

CUDA Programming Cook

CUDA Handbook Wilt

CUDA

Page 89: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Spezialisten GPU Computing Gems

„Jade“ und „Emerald“

Doku „Programming Guide“

„Best Practices Guide“

Web CudaZone bei nvidia.com

Parallel Forall (Blog)

Dokumentation docs.nvidia.com

CUDA

Page 90: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Einsteiger/Fortgeschritten „… in Action“

„… Programming Guide“

„Heterogenous Computing

with OpenCL“

Web Khronos

AMD‘s OpenCL Zone

Apple / Mac OS X

OpenCL

Page 91: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Bisher nur ein Buch

„C++ AMP“

Web

Microsoft

Intel‘s Prototyp/PoC „Shevlin Park“

C++ AMP

Page 92: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Bin beide Tage vor Ort

Sprechen Sie mich an!

[email protected]

Ansonsten

Happy GPU-Computing!

Fragen ?

Page 93: Tipps & Tricks für den erfolgreichen Einsatz von GPU-Computing

Freiberuflicher Dipl.-Inform.

Schwerpunkte

Parallele Systeme C++ und Java/JVM

GPU-Computing CUDA, OpenCL, C++ AMP

Weitere Informationen

http://www.dinkla.net

Last but not least