WebCL - Paralleles Rechnen im Web

 Tutorial
  0: Vorbereitung
  1: Detektor
  2: Platformen und Geräte
  3: Vektoraddition


 Kontakt
 webcl[ät)peter-strohm.de

2 Zwei Vektoren mit WebCL addieren

>>>> Direkt zum Beispiel <<<<

Die Addition von zwei Vektoren ist ein Standardbeispiel zur parallelen Programmierung. Vektoren werden addiert indem ihre jeweiligen Elemente addiert werden. Diese Element-Additionen sind unabhängig voneinander und können somit leicht parallelisiert werden.

$\left(\begin{array}{c}a_1 \\ a_2 \\ a_3 \\ .. \\ a_n\end{array}\right) + \left(\begin{array}{c}b_1 \\ b_2 \\ b_3 \\ .. \\ b_n\end{array}\right)= \left(\begin{array}{c}a_1 + b_1 \\ a_2 + b_2 \\ a_3 + b_3 \\ .. \\ a_n + b_n\end{array}\right)$

Wie auch bei OpenCL wird die eigentliche (parallele) Berechnung in sog. Kernels programmiert. Diese Kernels laufen bei der Ausführung des Programms dann parallel auf der GPU (bzw. Multicore CPU oder sonstiger OpenCL-Hardware).
Für das Beispiel der Vektoraddition benötigen wir also ein "Miniprogramm", das zwei Eingangswerte zu einem Ausgangswert addiert.
1<!DOCTYPE html>
2<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
3  <head>
4    <title>WebCL Beispiel 3</title>
5    <script type="text/javascript" id="addVectors">
6        "use strict";
7        /*global window */ // tells jslint that 'window' is defined!
8        /*global Uint32Array */
9        /*global WebCL */
10        var kernelsource = '__kernel void ckVectorAdd(\n\
11         __global unsigned int* vectorIn1,\n\
12                                         __global unsigned int* vectorIn2,\n\
13                                         __global unsigned int* vectorOut,\n\
14                                         unsigned int uiVectorWidth) {\n\
15                                unsigned int x = get_global_id(0);\n\
16                                if (x >= (uiVectorWidth))\n\
17                                {\n\
18                                    return;\n\
19                                }\n\
20                                \n\
21                                // Addition der zwei Vektorelemente:\n\
22                                vectorOut[x] = vectorIn1[x] + vectorIn2[x];\n\
23                                }';
24        function addVectors() {
25         var
26             outputstring,
27                output,
28                vectorLength,
29                UIvector1,
30                UIvector2,
31                platforms,
32                ctx,
33                i,
34                bufSize,
35                bufIn1,
36                bufIn2,
37                bufOut,
38                program,
39                devices,
40                kernel,
41                cmdQueue,
42                outBuffer,
43                dataObject1,
44                dataObject2,
45                localWS,
46                globalWS,
47                utils,
48                k;
49            outputstring = "";
50            output = window.document.getElementById("output");
51            try {
52                if (window.WebCL === undefined) {
53                    window.alert("Dein System unterstützt WebCL nicht. Siehe <a href=\"www.peter-strohm.de/webcl/index.php\">Peters WebCL Seite<\/a>");
54                    return false;
55                }
56
57                // Generate input vectors
58                vectorLength = 20;
59                UIvector1 = new Uint32Array(vectorLength);
60                UIvector2 = new Uint32Array(vectorLength);
61                for (i = 0; i < vectorLength; i = i + 1) {
62                    UIvector1[i] = Math.floor(Math.random() * 100); //Zufallszahl 0..99
63                    UIvector2[i] = Math.floor(Math.random() * 100); //Zufallszahl 0..99
64                }
65
66                // 1. : Die Liste der lokal verfügbaren WebCL _Platformen_ wird abgerufen.
67                // (jeder Platform können mehrere Devices zugeordnet sein.
68                platforms = WebCL.getPlatformIDs();
69                ctx = WebCL.createContextFromType([WebCL.CL_CONTEXT_PLATFORM,
70                                            platforms[0]],
71                                            WebCL.CL_DEVICE_TYPE_DEFAULT);
72                bufSize = vectorLength * 4; // Größe in Byte
73                output.innerHTML += "<br>Buffer size: " + bufSize + " bytes";
74                bufIn1 = ctx.createBuffer(WebCL.CL_MEM_READ_ONLY, bufSize);
75                bufIn2 = ctx.createBuffer(WebCL.CL_MEM_READ_ONLY, bufSize);
76                bufOut = ctx.createBuffer(WebCL.CL_MEM_WRITE_ONLY, bufSize);
77
78                program = ctx.createProgramWithSource(kernelsource);
79                devices = ctx.getContextInfo(WebCL.CL_CONTEXT_DEVICES);
80
81                try {
82                    program.buildProgram([devices[0]], "");
83                } catch (e1) {
84                    window.alert("Failed to build WebCL program. Error "
85                        + program.getProgramBuildInfo(devices[0], WebCL.CL_PROGRAM_BUILD_STATUS) + ": "
86                        + program.getProgramBuildInfo(devices[0], WebCL.CL_PROGRAM_BUILD_LOG));
87                    throw e1;
88                }
89
90                // Create kernel and set arguments
91                kernel = program.createKernel("ckVectorAdd");
92                kernel.setKernelArg(0, bufIn1);
93                kernel.setKernelArg(1, bufIn2);
94                kernel.setKernelArg(2, bufOut);
95                kernel.setKernelArg(3, vectorLength, WebCL.types.UINT);
96                         // Create command queue using the first available device
97                cmdQueue = ctx.createCommandQueue(devices[0], 0);
98
99                // Write the buffer to OpenCL device memory
100                dataObject1 = WebCL.createDataObject();
101                dataObject1.allocate(bufSize);
102                dataObject1.set(UIvector1);
103
104                dataObject2 = WebCL.createDataObject();
105                dataObject2.allocate(bufSize);
106                dataObject2.set(UIvector2);
107
108                cmdQueue.enqueueWriteBuffer(bufIn1, false, 0, dataObject1.length,
109                                             dataObject1, []);
110                cmdQueue.enqueueWriteBuffer(bufIn2, false, 0, dataObject2.length,
111                                             dataObject2, []);
112
113                // Init ND-range
114                localWS = [8];
115                globalWS = [Math.ceil(vectorLength / localWS) * localWS];
116
117
118                // Execute (enqueue) kernel
119                cmdQueue.enqueueNDRangeKernel(kernel, globalWS.length, [],
120                                              globalWS, localWS, []);
121
122                // Read the result buffer from OpenCL device
123                cmdQueue.enqueueReadBuffer(bufOut, false, 0, bufSize, dataObject1, []);
124                cmdQueue.finish(); //Finish all the operations
125
126                outBuffer = new Uint32Array(vectorLength);
127                utils = WebCL.getUtils();
128                utils.writeDataObjectToTypedArray(dataObject1, outBuffer);
129
130                for (k = 0; k < outBuffer.length; k = k + 1) {
131                    outputstring += UIvector1[k] + " + " + UIvector2[k] + " = " + outBuffer[k] + "<br \/>";
132                }
133
134                output.innerHTML = outputstring + "<br \/>";
135            } catch (e0) {
136                output.innerHTML = outputstring + "<br \/>";
137                output.innerHTML += "<b>Error:<\/b> <pre style='color:red;'>" + e0.toString() + "<\/pre>";
138                throw e0;
139            }
140        }

Kommentieren:

Name
Email Die Emailadresse wird nicht veröffentlicht und nicht weitergegeben
Kommentar

>> Startseite <<   ^ Seitenanfang ^    
Fehler? Kommentare? webcl ([ät)] peter-strohm Punkt de