簡體   English   中英

OpenCL C++ HelloWorld

[英]OpenCL C++ HelloWorld

下午好:我正在學習本教程中的OpenCL C++: 點擊(不是必須的)

該視頻使用CL API版本1.2 ,所以我從該回復中的鏈接下載了OpenCL 1.2標頭: https://stackoverflow.com/a/57017982/11968932

Visual Studio 2022未顯示任何錯誤,但程序會輸出以下符號:

╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠

它應該說"Hello World!" .

這是程序本身。 主持人:

#define CL_USE_DEPRECATED_OPENCL_1_2_APIS

#include <CL/cl.hpp>
#include <iostream>
#include <fstream>

int main() 
{
    std::vector<cl::Platform> platforms;
    cl::Platform::get(&platforms);

    auto platform = platforms.front();
    std::vector<cl::Device> devices;
    platform.getDevices(CL_DEVICE_TYPE_ALL, &devices);

    auto device = devices.front();

    std::ifstream helloWorldFile("HelloWorld.cl");
    std::string src(std::istreambuf_iterator<char>(helloWorldFile), (std::istreambuf_iterator<char>()) );

    cl::Program::Sources sources(1, std::make_pair(src.c_str(), src.length() + 1));

    cl::Context context(device);
    cl::Program program(context, sources);

    auto err = program.build("cl-std=CL1.2");

    char buf[16];
    cl::Buffer memBuf(context, CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY, sizeof(buf));
    cl::Kernel kernel(program, "HelloWorld", &err);
    kernel.setArg(0, memBuf);

    cl::CommandQueue queue(context, device);
    queue.enqueueTask(kernel);
    queue.enqueueReadBuffer(memBuf, CL_TRUE, 0, sizeof(buf), buf);

    std::cout << buf << " - buf" << std::endl;
}

HelloWorld.cl:

_kernel void HelloWorld(_global char* data)
{
    data[0] = 'H';
    data[1] = 'e';
    data[2] = 'l';
    data[3] = 'l';
    data[4] = 'o';
    data[5] = ' ';
    data[6] = 'W';
    data[7] = 'o';
    data[8] = 'r';
    data[9] = 'l';
    data[10] = 'd';
    data[11] = '!';
    data[12] = '\n';
}

謝謝;)

三個錯誤:

  1. 它是__kernelkernel ,但不是帶有一個下划線的_kernel __global也一樣
  2. cl::Buffer memBuf(context, CL_MEM_READ_WRITE, 16*sizeof(buf)); - 這里有兩件事是錯誤的: CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY CL_MEM_WRITE_ONLY | CL_MEM_READ_ONLY標志意味着設備端的緩沖區完全不可訪問,它只為第一個字符分配了 memory (忘記了16*sizeof(buf)
  3. queue.enqueueReadBuffer(memBuf, CL_TRUE, 0, 16*sizeof(buf), (void*)buf); - 忘記了16*sizeof(buf)

我還必須做auto err = program.build(); 沒有任何 arguments。

另請注意:

  • 雖然它有效,但堆棧分配 ( char buf[16]; ) 會限制緩沖區大小。 使用堆分配( char* buf = new char[16]; )代替(不要忘記delete[] buf; )。
  • 不要使用queue.enqueueTask(kernel); , 但是queue.enqueueNDRangeKernel(cl_kernel, cl::NullRange, cl::NDRange(...), cl::NDRange(32)); 反而。 有了這個,您可以指定全局和局部范圍。

最后,有點廣告:我創建了一個OpenCL-Wrapper來極大地簡化 OpenCL 的學習和工作。 這個 Wrapper 消除了跟蹤例如緩沖區大小或為 CPU 和設備提供重復緩沖區的需要。 您需要為 HelloWorld 示例編寫的代碼明顯更短、更容易:

#include "opencl.hpp"
int main() {
    const Device device(select_device_with_most_flops()); // compile OpenCL C code for the fastest available device
    const uint N = 16u; // size of vectors
    Memory<char> buf(device, N); // allocate memory on both host and device
    const Kernel HelloWorld(device, N, "HelloWorld", buf); // kernel that runs on the device
    HelloWorld.run(); // run add_kernel on the device
    buf.read_from_device(); // copy data from device memory to host memory
    println(buf.data());
}
#include "kernel.hpp" // note: string literals can't be arbitrarily long, so periodically interrupt with )+R(
string opencl_c_container() { return R( // ########################## begin of OpenCL C code ####################################################################

kernel void HelloWorld(global char* data) {
    data[0] = 'H';
    data[1] = 'e';
    data[2] = 'l';
    data[3] = 'l';
    data[4] = 'o';
    data[5] = 32; // spaces are wrongly converted with stringification macro, so use ascii code here instead of ' '
    data[6] = 'W';
    data[7] = 'o';
    data[8] = 'r';
    data[9] = 'l';
    data[10] = 'd';
    data[11] = '!';
    data[12] = '\n';
}

);} // ############################################################### end of OpenCL C code #####################################################################

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM