2016-07-28 38 views
0

Ich versuche zu lernen, wie OpenCL mit diesem Tutorial https://anteru.net/blog/2012/11/04/2016/index.html zu verwenden, aber ich glaube nicht, dass die Werte in den Float-Puffer auf nichts festgelegt werden. und wenn ich den Puffer am Ende lese, ist es alles 0s mit einer Ansicht Dezimalzahlen in wissenschaftlicher Notation wie es voller Zufallsspeicher ist. Ich werde den Code unten posten. Was der Kernel macht, ist in 3 Parameter zu nehmen, float buffer x, float buffer y und float a. const int i = get_global_id(0) und y[i] += a * x[i]; das Problem ist (ich denke), dass ich nie irgendwelche Zahlen in aBuffer oder bBuffer setzen, so dass die Multiplikationen und die Addition nichts bedeuten. aber eine seltsame Sache ist, dass, wenn ich den Kernel machen dies tun y[i] += a; es immer noch die gleiche Leistung gibt, wenn ich denke, es wäre 2.OpenCL-Puffer ist leer

main.cpp geben würde:

#include <iostream> 
#include <vector> 


#ifdef __APPLE__ 
#include "OpenCL/opencl.h" 
#else 
#include "CL/cl.h" 
#endif 


using namespace std; 




int main(int argc, const char * argv[]) { 
    cl_uint platformIdCount = 0; 
    clGetPlatformIDs(0, nullptr, &platformIdCount); 

    vector<cl_platform_id> platformIds(platformIdCount); 
    clGetPlatformIDs(platformIdCount, platformIds.data(), nullptr); 
    cout << "Platforms " << platformIdCount << endl; 

    cl_uint deviceIdCount = 0; 


    clGetDeviceIDs(platformIds[0], CL_DEVICE_TYPE_GPU, 0, nullptr, &deviceIdCount); 
    cout << "Devices " << deviceIdCount << endl; 

    vector<cl_device_id> deviceIds(deviceIdCount); 
    clGetDeviceIDs(platformIds[0], CL_DEVICE_TYPE_GPU, deviceIdCount, deviceIds.data(), nullptr); 


    const cl_context_properties contextProperties[] = { 

     CL_CONTEXT_PLATFORM, 
     reinterpret_cast<cl_context_properties>(platformIds[0]), 
    0,0 
}; 
    cl_int error = 0; 
    cl_context context = clCreateContext(contextProperties, deviceIdCount, deviceIds.data(), nullptr, nullptr, &error); 

    error = 0; 

    cl_mem aBuffer = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(float) * (64), nullptr, &error); 
    cl_mem bBuffer = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(float) * (64), nullptr, &error); 



    cl_program program; 

    clBuildProgram(program, deviceIdCount, deviceIds.data(), nullptr, nullptr, nullptr); 

    cl_kernel kernel1 = clCreateKernel(program, "SAXPY", &error); 

    clSetKernelArg(kernel1, 0, sizeof(cl_mem), aBuffer); 
    clSetKernelArg(kernel1, 1, sizeof(cl_mem), bBuffer); 
    static const float two = 2.0f; 
    clSetKernelArg(kernel1, 2, sizeof(float),&two); 

    const size_t globalWorkSize [] = {64,0,0}; 
    cl_command_queue queue; 
    clEnqueueNDRangeKernel(queue, kernel1, 1, nullptr, globalWorkSize, nullptr, 0, nullptr, nullptr); 



    float done[64]; 
    clEnqueueReadBuffer(queue, bBuffer, CL_TRUE, 0, sizeof(float)*64, done, 0, nullptr, nullptr); 
    for (int a = 0; a < 64; a++) { 
     cout << done[a] << endl; 
    } 




    clReleaseContext(context); 
    return 0; 
} 

.cl Datei:

kernel void SAXPY(__global float* x,__global float* y, float a){ 
    const int i = get_global_id(0); 
    //y[i] = 2.0f; 
    y[i] += a * x[i]; 
} 
+0

Versuchen Aufruf 'clFinish (Warteschlange);' nach 'clEnqueueNDRangeKernel (Queue, kernel1, 1, nullptr, globalWorkSize, nullptr, 0, nullptr, nullptr); '. – sarasvati

+0

was macht das? –

+0

Es blockiert den aktuellen CPU-Thread und wartet, bis alle Befehle in der 'Warteschlange' vom OpenCL-Gerät (d. H. GPU) verarbeitet wurden. Es ist möglich, dass Ihr 'kernel1' die Berechnung nicht abgeschlossen hat, als Sie versucht haben, die Werte des Puffers zu lesen. – sarasvati

Antwort

1

Erstens, wenn Kernel-Argument festlegen, müssen Sie pass pointer auf das Speicherobjekt:

clSetKernelArg(kernel1, 0, sizeof(cl_mem), &aBuffer); // &aBuffer, not aBuffer 
clSetKernelArg(kernel1, 1, sizeof(cl_mem), &bBuffer); // &bBuffer, not bBuffer 
Zweitens

, nicht wahr create command queue:

cl_command_queue queue = clCreateCommandQueue(context, deviceIds[0], 0, nullptr); 

Drittens Sie nicht nennen clCreateProgramWithSource() vor clBuildProgram().

Darüber hinaus versuchen, die cl_mem Objekte zu initialisieren:

cl_float* mem = (cl_float*) malloc(sizeof(cl_float)*64); 
for(int i=0; i<64; i++) 
    mem[i] = i; 

cl_mem aBuffer = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(cl_float) * (64), mem, &error); 
cl_mem bBuffer = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(cl_float) * (64), mem, &error); 

free(mem); 

Festcode:

#include <iostream> 
#include <vector> 

#ifdef __APPLE__ 
#include <OpenCL/cl.h> 
#else 
#include "CL/cl.h" 
#endif 

using namespace std; 


int main(int argc, const char * argv[]) { 
    cl_uint platformIdCount = 0; 
    clGetPlatformIDs(0, nullptr, &platformIdCount); 

    vector<cl_platform_id> platformIds(platformIdCount); 
    clGetPlatformIDs(platformIdCount, platformIds.data(), nullptr); 

    cl_uint deviceIdCount = 0; 
    clGetDeviceIDs(platformIds[0], CL_DEVICE_TYPE_GPU, 0, nullptr, &deviceIdCount); 

    vector<cl_device_id> deviceIds(deviceIdCount); 
    clGetDeviceIDs(platformIds[0], CL_DEVICE_TYPE_GPU, deviceIdCount, deviceIds.data(), nullptr); 

    const cl_context_properties contextProperties[] = { 

     CL_CONTEXT_PLATFORM, 
     (cl_context_properties)platformIds[0], 
     0 
    }; 

    cl_int error = 0; 
    cl_context context = clCreateContext(contextProperties, 1, &deviceIds[0], [](const char* errinfo, const void* private_info, size_t cb, void* user_data) -> void { 
     /* context-creation and runtime error handler */ 
     cout << "Context error: " << errinfo << endl; 
    }, nullptr, &error); 


    cl_float* mem = (cl_float*) malloc(sizeof(cl_float)*64); 
    for(int i=0; i<64; i++) 
     mem[i] = i; 

    cl_mem aBuffer = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(cl_float) * (64), mem, &error); 
    cl_mem bBuffer = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(cl_float) * (64), mem, &error); 

    free(mem); 

    cl_program program; 
    string src = "__kernel void SAXPY(__global float* x, __global float* y, float a){" 
        "size_t i=get_global_id(0);" 
        "y[i]=a*x[i];" 
       "}"; 

    const char* sources[] = {src.c_str()}; 
    const size_t lens[] = {src.length()}; 

    program = clCreateProgramWithSource(context, 1, sources, lens, &error); 
    clBuildProgram(program, 1, &deviceIds[0], nullptr, nullptr, nullptr); 

    cl_kernel kernel1 = clCreateKernel(program, "SAXPY", &error); 
    clSetKernelArg(kernel1, 0, sizeof(cl_mem), &aBuffer); 
    clSetKernelArg(kernel1, 1, sizeof(cl_mem), &bBuffer); 
    static const float two = 2.0f; 
    clSetKernelArg(kernel1, 2, sizeof(float),&two); 

    const size_t globalWorkSize [] = {64,0,0}; 
    cl_command_queue queue = clCreateCommandQueue(context, deviceIds[0], 0, nullptr); 

    clEnqueueNDRangeKernel(queue, kernel1, 1, nullptr, globalWorkSize, nullptr, 0, nullptr, nullptr); 

    float done[64]; 
    clEnqueueReadBuffer(queue, bBuffer, CL_TRUE, 0, sizeof(float)*64, done, 0, nullptr, nullptr); 
    for (int a = 0; a < 64; a++) 
     cout << done[a] << endl; 

    clReleaseContext(context); 
    return 0; 
} 
+0

Dank, bemerkte ich einige dieser Dinge, und ich verpasste eine Reihe von Funktionen. Jetzt, da ich den Quellcode gefunden habe, werde ich das in ein anderes Projekt kopieren und damit ein bisschen spielen –

+0

Ich habe noch eine Frage. Sarasvati hat gerade die Kernel-Funktion eingegeben, aber ich denke, dass man damit tatsächlich aus einer Datei lesen kann. ifstream infile {"Datei.txt"}; Zeichenfolge file_contents {istreambuf_iterator (Infile), istreambuf_iterator ()}; Warum nimmt String Parameter? Ich wusste nicht, dass Strings dies taten. Und warum sind die beiden Parameter fast identisch, was sind sie? –

+0

Ok ich könnte es verstehen, sag mir wenn ich falsch liege. Die letzten Parameter zeigen also wie ein Null-Terminator oder ähnliches auf das Ende der Datei. Und der erste Parameter bedeutet, dass chars von infile genommen und in file_contents gestellt wird, bis das char gleich null ist. –