Concurrency Gerard Tel / Jacco Bikker - november 2017 februari 2018 College 10: OpenCL (1) Welkom!
Previously in Concurrency
Concurrency College 8 Patronen 3 SIMD System.Numerics.Vectors namespace System.Numerics { public struct Vector3 : IEquatable<Vector3>, IFormattable { public float X; public float Y; public float Z; public Vector3(float value); public Vector3(Vector2 value, float z); public Vector3(float x, float y, float z); public static Vector3 operator -(Vector3 value); public static Vector3 operator -(Vector3 left, Vector3 right); public static bool operator!=(vector3 left, Vector3 right); public static Vector3 operator *(float left, Vector3 right); public static Vector3 operator *(Vector3 left, float right); public static Vector3 operator *(Vector3 left, Vector3 right); public static Vector3 operator /(Vector3 value1, float value2); public static Vector3 operator /(Vector3 left, Vector3 right); public static Vector3 operator +(Vector3 left, Vector3 right); public static bool operator ==(Vector3 left, Vector3 right);
Concurrency College 8 Patronen 4 SIMD System.Numerics.Vectors Voorbeeld: C# code: Vector3 D = Vector3.Normalize( T - P ); Assembler: vsubps xmm0,xmm1,xmm6 ; subtract vmovaps xmm1,xmm0 vdpps xmm1,xmm1,xmm0,0f1h ; dot vcvtss2sd xmm1,xmm1,xmm1 ; float to double vsqrtsd xmm1,xmm0,xmm1 ; square root vcvtsd2ss xmm1,xmm1,xmm1 ; double to float vmovupd xmmword ptr [rsp+40h],xmm0 vmovss xmm0,dword ptr [7FE90EEA518h] vdivss xmm0,xmm0,xmm1 ; division...
Concurrency College 8 Patronen 5 SIMD Klaar? Nee. Vector3 D = Vector3.Normalize( T - P ); Vector3 A = T P // 75% float B = dot( A, A ) // 75% Vector3 C = { B, B, B } // 75% Vector3 D = A / C // 75%
Concurrency College 8 Patronen 6 SIMD Scalar Flow Vector3 D = Vector3.Normalize( T - P ); Wat gebeurt hier nu eigenlijk echt? Vector3 d = T P; float dot = d.x * d.x + d.y * d.y + d.z * d.z; float length = sqrt( dot ); d /= length; D = D;
Concurrency College 8 Patronen 7 SIMD Scalar Flow Vector3 D = Vector3.Normalize( T - P ); Wat gebeurt hier nu eigenlijk echt? float dx = T.x P.x; float dy = T.y P.y; float dz = T.z P.z; float dot = d.x * d.x; float v1 = d.y * d.y; float v2 = d.z * d.z; dot += v1; dot += v2; float length = sqrt( dot ); D.x = dx / length; D.y = dy / length; D.z = dz / length; Scalar flow: Het programma, teruggebracht tot de kleinste elementen, waarbij elke berekening een of twee operanden transformeert in een resultaat.
Concurrency College 8 Patronen 8 SIMD Scalar Flow Vector3 D = Vector3.Normalize( T - P ); Vectorizatie: Optimaal normaliseren met SIMD: input is 4x T, 4x P opgedeeld in componenten: Tx4, Ty4, Tz4 en Px4, Py4, Pz4 output is 4x D: Dx4, Dy4, Dz4 float dx = T.x P.x; float dy = T.y P.y; float dz = T.z P.z; float dot = d.x * d.x; float v1 = d.y * d.y; float v2 = d.z * d.z; dot += v1; dot += v2; float length = sqrt( dot ); D.x = dx / length; D.y = dy / length; D.z = dz / length; float4 dx4 = sub4( Tx4, Px4 ); float4 dy4 = sub4( Ty4, Py4 ); float4 dz4 = sub4( Tz4, Pz4 ); float4 dot4 = mul4( dx4, dx4 ); float4 v1 = mul4( dy4, dy4 ); float4 v2 = mul4( dz4, dz4 ); dot4 = add4( dot4, v1 ); dot4 = add4( dot4, v2 ); float4 length4 = sqrt4( dot4 ); Dx4 = div4( dx4 / length4 ); Dy4 = div4( dy4 / length4 ); Dz4 = div4( dz4 / length4 );
Concurrency College 8 Patronen 9 SIMD SIMD Data class Particle { Vector3 position; Vector3 velocity; float mass; } Particle p[1024]; Optimaal normaliseren met SIMD: input is 4x T, 4x P opgedeeld in componenten: Tx4, Ty4, Tz4 en Px4, Py4, Pz4 output is 4x D: Dx4, Dy4, Dz4 = AoS Array of Structures Structure of Arrays SoA float px[1024]; float py[1024]; float pz[1024]; float vx[1024]; float vy[1024]; float vz[1024]; float mass[1024]; Vector4 px4[256]; Vector4 py4[256]; Vector4 pz4[256]; Vector4 vx4[256]; Vector4 vy4[256]; Vector4 vz4[256]; Vector4 mass4[256];
Concurrency College 8 Patronen 10 SIMD Vectorization Digest: Vectorizatie begint met het identificeren van een scalar flow. Uitgevoerd met vector artithmetic voeren we 4 onafhankelijke, identieke flows in parallel uit. De data moet passend zijn voor de vector flow: waar we eerst pos.x gebruiken, gebruiken we nu pos.x4 (en dus niet pos.xyzw!), waar we eerst de constante PI gebruiken, gebruiken we nu { PI, PI, PI, PI }. We noemen deze data layout struct of arrays. Theoretische winst is 4x. Maar: Er is bijna altijd sprake van enige overhead om data in het juiste formaat te krijgen. De C# JIT compiler is niet optimaal.
Concurrency College 8 Patronen 11 SIMD SIMD en Control Flow Wat doen we wanneer niet alle lanes hetzelfde willen?? A B
Concurrency College 8 Patronen 12 SIMD
Agenda: Introductie OpenCL OpenCL / C# Workgroups Tot Slot
Concurrency College 10 OpenCL (1) 14 Introductie Heterogene Systemen Een modern system heeft naast 1 (of 2) CPUs een grafische co-processor: de GPU.
Concurrency College 10 OpenCL (1) 15 Introductie AMD: RX Vega 64 631 NVidia: GTX1080Ti 709 Intel: i9-7980xe 1899 Xeon Phi 7120P 3167 484 GB/s 13.7 TFLOPS 320 GB/s 11.3 TFLOPS 50 GB/s 1.1 TFLOPS 352 GB/s ~6 TFLOPS
Concurrency College 10 OpenCL (1) 16 Introductie Heterogene Systemen Een modern system heeft naast 1 (of 2) CPUs een grafische co-processor: de GPU. GPU: veel rekenkracht: >10 Tflops (i9: ~1 Tflops) veel bandbreedte: 512GB/s (i9: 50GB/s)
Concurrency College 10 OpenCL (1) 17 Introductie GPU Performance Rekenkracht: Beperkt executiemodel 32-wide SIMT Bandbreedte: Streaming executiemodel Expliciete geheugenarchitectuur
Concurrency College 10 OpenCL (1) 18 Introductie Beperkt Executiemodel Geen branch prediction Een taak tegelijk Geen context switching Beperkte super-scalar pipeline Geen out-of-order execution En: Lage kloksnelheid (~1Ghz)
Concurrency College 10 OpenCL (1) 19 Introductie GPU: Massively Parallel Een GPU bestaat uit: * 24 Shading Multiprocessors Per SM: 128 CUDA cores (4 groepen van 32) Totaal: 3072 CUDA cores. Eén SM kan maximaal 2048 threads uitvoeren: 16 per CUDA core. Het mechanisme wat hier voor gebruikt wordt lijkt op hyperthreading. Het maximale aantal threads is dus 49.152. * Titan X / Maxwell architectuur
Concurrency College 10 OpenCL (1) 20 Introductie Beperkt Executiemodel Een GPU groepeert de threads in warps van 32 threads, en voert deze uit met SIMT: Single Instruction, Multiple Thread Een GPU is dus eigenlijk een 32-wide vector machine.
Concurrency College 10 OpenCL (1) 21 Introductie GPGPU Samenvatting: Tienduizenden threads In groepen van 32 Een GPU is ongeschikt voor taak-parallellisme. Een GPU is zeer geschikt voor data parallellisme, maar: alleen wanneer de parallelle taken een identieke flow hebben.
Concurrency College 10 OpenCL (1) 22 Introductie GPGPU CPU GPU
Concurrency College 10 OpenCL (1) 23 If you were plowing a field, which would you rather use? Two strong oxen, or 1024 chickens? - Seymour Cray
Concurrency College 10 OpenCL (1) 24 Introductie Heterogene Systemen In een heterogeen systeem kan een applicatie zowel de CPU als de GPU benutten. Doel: data-parallelle taken uitvoeren op de GPU; taak-parallel werk en serieel werk op de CPU. De GPU is dus géén vervanging voor de CPU.
Agenda: Introductie OpenCL OpenCL / C# Workgroups Tot Slot
Concurrency College 10 OpenCL (1) 26 OpenCL OpenCL Standaard Framework voor het ontwikkelen van software die uitgevoerd kan worden op heterogene platformen, bestaande uit CPUs, GPUs, DSPs, FPGAs en andere processoren. Computing System Compute Devices Compute Units Processing Elements OpenCL Memory Hierarchy: Global memory Read-only memory Local memory Per-element private memory CPU Cores SIMD Lanes GPU SMs CUDA cores
Concurrency College 10 OpenCL (1) 27 OpenCL OpenCL Standaard Het OpenCL executiemodel is fundamenteel parallel, en gaat uit van regular parallelism: meerdere processing elements voeren dezelfde code uit: een kernel.
Concurrency College 10 OpenCL (1) 28 OpenCL Kernel #define C(p) min(1.,sqrt(10.*abs(length(p-.5)-.4))) #define D(p,o) ((d=length(p-o)*5.)<=.6? d:1.) void mainimage( out vec4 O, in vec2 pos ) { vec2 res = iresolution.xy; vec2 C = vec2( 0.5, 0.5 ); vec2 d = pos / res - C; if (length( d ) <.2) O.xyz = vec3( 1, 0, 0 ); else O.xyz = vec3( 0, 0, 0 ); }
Concurrency College 10 OpenCL (1) 29 OpenCL Kernel https://www.shadertoy.com/view/4lsgd1 bool test( out vec3 N, in vec3 D, in vec3 s, in float r ) { float A = dot( D, D ), B = dot( D, s )*(-2.0); float C = dot( s, s ) - r*r, det = B*B - 4.0*A*C; if (det < 0.0 ) return false; float t = (-B+sqrt(det)) / (2.0*A); N = normalize( D*t - s ); return true; } void mainimage( out vec4 color, in vec2 pos ) { float Y = pos.y / iresolution.y; vec3 N, Sky = vec3( 0.45, 0.75, 1.0 )*Y*0.4; vec3 V = normalize( vec3( (pos.xy - iresolution.xy*0.5) / iresolution.xx, 1.0 )); color = vec4(sky,1.0); if (!test( N, V, vec4(0,0,5), 1.0 )) return; vec3 H = normalize( V - reflect(v,n)), L = normalize( vec3(1.0,1.0,1.0)); float dotnl = max(dot(n,l),0.), dothl = max(dot(h,l),0.), spec = pow(dothl,32.); color = vec4(vec3(1,0.5,0.5)*dotnl*0.9 + vec3(1,1,1)*spec*0.9 + Sky,1.); }
Concurrency College 10 OpenCL (1) 30 OpenCL Kernel Shaders op Shadertoy: korte programma s die uitgevoerd worden voor elke pixel van een bitmap. Regular parallelism / Map Geen synchronisatie tussen threads. Uitvoer is 1 pixel, op een vaste locatie. pos pos pos pos pos pos pos pos K K K K K K K K Executie op GPU hardware: Elke pixel van de bitmap is een thread. Groepering van threads in warps en de verdeling over SMs wordt overgelaten aan WebGL / de driver. Eventuele input data voor een kernel wordt aangeboden in de vorm van textures. color color color color color color color color
Concurrency College 10 OpenCL (1) 31 OpenCL Kernel Kernels in OpenCL: korte programma s die uitgevoerd worden voor elke taak in een lijst. Regular parallelism / Map Synchronisatie tussen threads is mogelijk. In- en uitvoer kan complex zijn. in in in in in in in in K K K K K K K K Executie op GPU hardware: Elke taak in de lijst is een thread. Groepering van threads in warps en de verdeling over SMs kan expliciet gespecificeerd worden. Input- en output data in de vorm van textures en/of generieke buffers. Expliciete controle over de memory hierarchy. out out out out out out out out
Concurrency College 10 OpenCL (1) 32 OpenCL OpenCL Specificatie Gebaseerd op C99 Extensies: address space qualifiers work-items workgroups vector types synchronizatie Ingebouwde functies: image manipulation work item manipulation math functies Beperkingen: geen functiepointers geen recursie kernel void SAXPY( global float* x, global float* y, float a, write_only image2d_t image ) { int i = get_global_id( 0 ); y[i] += a * cos( x[i] ); y[i] += a * native_cos( x[i] ); float3 tmp = (float3)(a, a, a ); int2 pos = (int2)(i,0); write_imagef( image, pos, tmp ); tmp = native_cos( tmp ); y[i] += tmp.x; y[i] += tmp.y; y[i] += tmp.z; }
Agenda: Introductie OpenCL OpenCL / C# Workgroups Tot Slot
Concurrency College 10 OpenCL (1) 34 OpenCL / C# OpenTK / Cloo OpenCL kan in C# gebruikt worden via de Cloo library: using Cloo; Om een OpenCL kernel te kunnen gebruiken hebben we nodig: een compute platform een OpenCL context een OpenCL command queue een OpenCL program de kernel
Concurrency College 10 OpenCL (1) 35 OpenCL / C# Devices & Vendors: Compute Platform Het Compute Platform is de interface naar de vendor-specific implementatie van OpenCL. In een systeem met een NVidia GPU zijn in principe twee OpenCL platforms aanwezig: 1. De NVidia OpenCL implementatie; 2. De Intel OpenCL implementatie (voor de CPU). Platform ComputePlatform platform = ComputePlatform.Platforms[0]; Console.Write( platform.name ); // NVIDIA CUDA Console.Write( platform.profile ); // FULL PROFILE
Concurrency College 10 OpenCL (1) 36 OpenCL / C# OpenCL Context In de context wordt de state van de OpenCL API bijgehouden. ComputeContext context = new ComputeContext( ComputeDeviceTypes.Gpu, new ComputeContextPropertyList( platform ), null, IntPtr.Zero ); Platform Context
Concurrency College 10 OpenCL (1) 37 OpenCL / C# Program Een OpenCL program is een collectie kernels. Ook wanneer we maar één kernel hebben wordt deze ondergebracht in een program. var streamreader = new StreamReader( "../../program.cl" ); string clsource = streamreader.readtoend(); streamreader.close(); // create program with opencl source ComputeProgram program = new ComputeProgram( context, clsource ); Compileren van OpenCL code: program.build( null, null, null, IntPtr.Zero ); Platform Context Program
Concurrency College 10 OpenCL (1) 38 OpenCL / C# Kernel We kunnen nu de kernel opvragen: ComputeKernel kernel = program.createkernel( "device_function" ); Platform Context Program Kernel
Concurrency College 10 OpenCL (1) 39 OpenCL / C# Kernel Arguments Stel dat we de volgende kernel willen uitvoeren: kernel void device_function( global float* x, float a ) { int i = get_global_id( 0 ); x[i] *= a; } Deze kernel heeft twee arguments. We geven de data door vanuit C# met: kernel.setmemoryargument( 0, buffer ); kernel.setvalueargument( 1, 3.14159265359f ); Platform Context Program Kernel Arguments
Concurrency College 10 OpenCL (1) 40 OpenCL / C# Buffers In het voorbeeld is een van de argumenten een array van floats. kernel void device_function( global float* x, float a ) { int i = get_global_id( 0 ); x[i] *= a; } Platform Context Program Kernel Arguments Buffers In C#: float [] data = new float[65536]; We maken hier een buffer van waarmee OpenCL kan werken: var flags = ComputeMemoryFlags.ReadWrite ComputeMemoryFlags.UseHostPointer; buffer = new ComputeBuffer<float>( context, flags, data );
Concurrency College 10 OpenCL (1) 41 OpenCL / C# Queue Alles staat nu klaar om uitgevoerd te worden. Kernel execution gaat via een job queue: ComputeCommandQueue queue = new ComputeCommandQueue( context, context.devices[0], 0 ); queue.execute( kernel, null, new long [] { 512 * 512 }, null, null ); queue.finish(); Als laatste stap lezen we de GPU buffer terug naar de C# array. queue.readfrombuffer( buffer, ref data, true, null ); Platform Context Program Kernel Arguments Buffers Queue
Concurrency College 10 OpenCL (1) 42 OpenCL / C# Recap Voor het uitvoeren van een kernel hebben we nodig: een OpenCL platform: platform = ComputePlatform.Platforms[0]; een OpenCL context: context = new ComputeContext( ); een program: program = new ComputeProgram( context, clsource ); de kernel: kernel = program.createkernel( "device_function" ); een job queue: queue = new ComputeCommandQueue( ); We zetten (eenmalig / voor updates) de arguments van de kernel met: SetMemoryArgument / SetValueArgument De kernel wordt uitgevoerd door een job aan de queue toe te voegen: queue.execute( kernel, null, new long [] { N }, null, null ); Platform Context Program Kernel Arguments Buffers Queue
Concurrency College 10 OpenCL (1) 43 OpenCL / C# Voorbeeld Het berekenen van de Mandelbrot set: M = cεc lim n Z n, Z 0 = c, Z n+1 = Z n 2 + c De verzameling M van alle complexe getallen waarvoor geldt dat de recursieve functie Z n voor c niet naar oneindig gaat. In pseudocode: Z re = c real, Z imaginary = c imaginary isinside = true for( n = 0; n < iterations; n++ ) { if (Z 2 real + Z 2 imaginary > 4) { isinside = false; break; } } Z imaginary = 2 Z real Z imaginary + c imaginary Z real = Z 2 real Z 2 imaginary + c real
Concurrency College 10 OpenCL (1) 44 OpenCL / C# Mandelbrot kernel void device_function( global int* a, float t ) { // adapted from inigo quilez - iq/2013 int id = get_global_id( 0 ); if (id >= (512 * 512)) return; float2 fragcoord = (float2)( (id & 511), (float)(id >> 9) ), resolution = (float2)( 512, 512 ); float3 col = (float3)( 0.f, 0.f, 0.f ); for( int m = 0; m < 2; m++ ) for( int n = 0; n < 2; n++ ) { float2 p = -resolution + 2.f * (fragcoord + (float2)(.5f * (float)m,.5f * (float)n )); float w = (float)( 2 * m + n ), l = 0.0f; float time = t +.5f * (1.f / 24.f) * w / 4.f; float zoo =.32f +.2f * cos(.07f * time ); float coa = cos(.15f * (1.f - zoo) * time ); float sia = sin(.15f * (1.f - zoo) * time ); zoo = pow( zoo, 8.f ); float2 xy = (float2)( p.x * coa - p.y * sia, p.x * sia + p.y * coa ); float2 c = (float2)( -.745f,.186f ) + xy * zoo, z = (float2)( 0.f, 0.f ); for( int i = 0; i < 256; i++ ) { z = (float2)( z.x * z.x - z.y * z.y, 2.f * z.x * z.y ) + c; if (dot( z, z ) > 65536.f) break; else l += 1.f; } float sl = l - log2( log2( dot( z, z ) ) ) + 4.f; float al = smoothstep( -.1f, 0.f, 1.f ); l = mix( l, sl, al ); col +=.5f +.5f * cos( 3.f + l * 0.15f + (float3)(.0f,.6f, 1.f ) ); } int r = (int)min( 255.0f, 64.0f * col.x ); int g = (int)min( 255.0f, 64.0f * col.y ); int b = (int)min( 255.0f, 64.0f * col.z ); a[id] = (r << 16) + (g << 8) + b; }
Concurrency College 10 OpenCL (1) 45 OpenCL / C#
Concurrency College 10 OpenCL (1) 46 OpenCL / C#
Agenda: Introductie OpenCL OpenCL / C# Workgroups Tot Slot
Concurrency College 10 OpenCL (1) 48 Workgroups Verdeling van Threads over de SMs In de Mandelbrot renderer hebben we: 512 * 512 = 262.144 threads. De Titan X kan maximaal 49.152 threads tegelijk uitvoeren. De output wordt dus door minstens 5 batches van 49.152 pixels en 1 batch van 16384 pixels verwerkt. Bij deze batch-grootte zijn er per SM 49.152/24 = 2048 threads actief, in 64 warps. Workgroup.
Concurrency College 10 OpenCL (1) 49 Workgroups Verdeling van Threads over de SMs per SM zijn 2048 threads actief, in 64 warps. In het Mandelbrot voorbeeld: 2048 threads voor 2048 pixels, bij een resolutie van 512x512: de pixels van de eerste 4 regels. for( int i = 0; i < 256; i++ ) { z = (float2)(z.x*z.x-z.y*z.y, 2.f*z.x*z.y) + c; if (dot( z, z ) > 65536.f) break; else l += 1.f; } Wat gebeurd er als 1 thread een break doet, en de andere threads door willen gaan?
Concurrency College 10 OpenCL (1) 50 Workgroups Occupancy z=5; if (cond1) 1111 Wat gebeurd er als 1 thread een break doet, en de andere threads door willen gaan? De threads in een warp worden in lockstep uitgevoerd: iedere thread voert dezelfde instructie uit. Masking wordt gebruikt om streams tijdelijk uit te schakelen. Een break in sommige threads in een warp betekent dat sommige threads inactief worden. Occupancy: aantal actieve threads per SM maximaal aantal threads per SM x = y + z; if (cond2) w = t + u; else w = t u; p = q + r; else x = y z; x++; 1110 1000 0110 1110 0001 1111
Concurrency College 10 OpenCL (1) 51 Workgroups Occupancy Wanneer we de totale taak als een 2D probleem beschouwen verbeterd de occupancy: Tiles hebben een betere program flow coherence dan regels.
Concurrency College 10 OpenCL (1) 53 Workgroups Experiment queue.execute( kernel, null, new long [] { 512 * 512 }, null, null ); wordt: int [] worksize = { 512, 512 }; queue.execute( kernel, null, worksize, null, null ); Voor t = 21.5: fps = 30.0 int [] worksize = { 512, 512 }; int [] localsize = { 32,... }; // 2, 4, 8, 16 queue.execute( kernel, null, worksize, localsize, null ); fps = 60.0
Concurrency College 10 OpenCL (1) 54 Workgroups Workgroup Size Waarom is de workgroup size van belang? Een SM heeft een beperkt aantal registers: 64K voor Kepler en Maxwell. 2048 threads = 32 32-bitregisters per thread. Wanneer de compiler onvoldoende registers beschikbaar heeft wordt local memory gebruikt.
Concurrency College 10 OpenCL (1) 55 Workgroups Workgroup Size Waarom is de workgroup size van belang? Een SM heeft snel local memory dat toegankelijk is voor alle threads op de SM.
Concurrency College 10 OpenCL (1) 56 Workgroups Workgroup Size Waarom is de workgroup size van belang? De threads in een workgroup kunnen barriers gebruiken voor synchronisatie.
Agenda: Introductie OpenCL OpenCL / C# Workgroups Tot Slot
Concurrency College 10 OpenCL (1) 58 Tot Slot GL Interop Data flow in Mandelbrot: screen (template) texture Buffer (host) t ReadFromBuffer Buffer (device, write-only) host Execute device
Concurrency College 10 OpenCL (1) 59 Tot Slot GL Interop OpenCL kan een OpenGL texture gebruiken als input / output. Voordeel: de data is al op de GPU, geen verkeer. Voorwaarden: OpenGL context moet gekoppeld worden aan OpenCL context OpenGL texture moet gelocked worden voor OpenCL
Concurrency College 10 OpenCL (1) 60 Tot Slot GL Interop OpenCL / OpenGL koppelen: [System.Runtime.InteropServices.DllImport("opengl32", SetLastError = true)] static extern IntPtr wglgetcurrentdc(); IntPtr glhandle = (GraphicsContext.CurrentContext as IGraphicsContextInternal).Context.Handle; IntPtr wglhandle = wglgetcurrentdc(); var p1 = new ComputeContextProperty(ComputeContextPropertyName.Platform, platform.handle.value); var p2 = new ComputeContextProperty(ComputeContextPropertyName.CL_GL_CONTEXT_KHR, glhandle); var p3 = new ComputeContextProperty(ComputeContextPropertyName.CL_WGL_HDC_KHR, wglhandle); var cpl = new ComputeContextPropertyList(new ComputeContextProperty[] { p1, p2, p3 }); context = new ComputeContext( ComputeDeviceTypes.Gpu, cpl, null, IntPtr.Zero );
Concurrency College 10 OpenCL (1) 61 Tot Slot GL Interop OpenGL texture voor interop aanmaken: float [] texdata = new float[512 * 512 * 4]; ComputeImage2D texbuffer; int texid = GL.GenTexture(); GL.BindTexture( TextureTarget.Texture2D, texid ); GL.TexParameter( TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)textureminfilter.nearest ); GL.TexParameter( TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)texturemagfilter.nearest ); GL.TexImage2D( TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba32f, 512, 512, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgb, PixelType.Float, texdata ); flags = ComputeMemoryFlags.WriteOnly; texbuffer = ComputeImage2D.CreateFromGLTexture2D( context, flags, (int)texturetarget.texture2d, 0, texid );
Concurrency College 10 OpenCL (1) 62 Tot Slot GL Interop OpenGL texture locken / unlocken: List<ComputeMemory> c = new List<ComputeMemory>() { texbuffer }; queue.acquireglobjects( c, null ); queue.execute( kernel, null, worksize, localsize, null ); queue.finish(); queue.releaseglobjects( c, null );
Concurrency College 10 OpenCL (1) 63 Tot Slot GL Interop Render-to-texture is de meest gebruikte toepassing voor GL interop. Andere toepassingen: Mesh simplification Procedural landscapes / meshes Particle systems
Agenda: Introductie OpenCL OpenCL / C# Workgroups Tot Slot
Concurrency College 10 OpenCL (1) 65 Tot Slot Literatuur NVIDIA s Fermi: The First Complete GPU Computing Architecture http://www.nvidia.com/content/pdf/fermi_white_papers/ p.glaskowsky_nvidia's_fermi-the_first_complete_gpu_architecture.pdf Boek: 2.4.3, 2.4.4
Concurrency Gerard Tel / Jacco Bikker - november 2017 februari 2018 EINDE van OpenCL (1) volgende college: OpenCL (2)