От OpenCL C++ wrapper spec :
cl :: Program :: Program возвращает действительный программный объект, а err устанавливается в CL_SUCCESS, если объект программы создан успешно. В противном случае, она возвращает один из следующих значений ошибок, возвращаемых в ERR [...]
Ваш программный объект, скорее всего, не создан должным образом, изменить свою строительную программу вызова использовать параметр err
после этой подписи
cl::Program::Program(const Context& context, const Sources& sources, cl_int * err = NULL)
И удостоверьтесь, что err == CL_SUCCESS
перед тем, как делать что-либо еще с вашим программным объектом.
Большинство вызовов OpenCL позволяют передавать указатель на параметр ошибки. Вы действительно должны это сделать и проверить его после ваших звонков (по крайней мере, в отладочных сборках, я думаю), чтобы уменьшить будущие головные боли.
Хорошо, поэтому я немного изменил ваш исходный код. Здесь я объясню свои изменения сразу после.
#define __NO_STD_VECTOR
#define __CL_ENABLE_EXCEPTIONS
#include <CL/cl.hpp>
#include <iostream>
#include <fstream>
#include <string>
#include <CL/cl.h>
#define ARRAY_SIZE 128
using namespace std;
using namespace cl;
int main(int, char**)
{
int err;
float my2D[ARRAY_SIZE * ARRAY_SIZE] = { 0 };
for(int i = 0; i < ARRAY_SIZE * ARRAY_SIZE; i++)
{
my2D[i] = 5;
}
cl::vector <Platform> platforms;
err = Platform::get(&platforms);
if(err != CL_SUCCESS) {
std::cout << "Platform::get failed - " << err << std::endl;
std::cin.get();
}
cl_context_properties cps[3] = { CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[0]()), 0 };
Context context(CL_DEVICE_TYPE_ALL, cps, nullptr, nullptr, &err);
if(err != CL_SUCCESS) {
std::cout << "Context::Context failed - " << err << std::endl;
std::cin.get();
}
cl::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>(&err);
if(err != CL_SUCCESS) {
std::cout << "Context::getInfo failed - " << err << std::endl;
std::cin.get();
}
CommandQueue queue = CommandQueue(context, devices[0], 0, &err);
if(err != CL_SUCCESS) {
std::cout << "CommandQueue::CommandQueue failed - " << err << std::endl;
std::cin.get();
}
int W = ARRAY_SIZE; //i.width();
int H = ARRAY_SIZE; //i.height();
Buffer d_ip = Buffer(context, CL_MEM_READ_ONLY, W*H*sizeof(float), nullptr, &err);
if(err != CL_SUCCESS) {
std::cout << "Buffer::Buffer 1 failed - " << err << std::endl;
std::cin.get();
}
Buffer d_op = Buffer(context, CL_MEM_WRITE_ONLY, W*H*sizeof(float), nullptr, &err);
if(err != CL_SUCCESS) {
std::cout << "Buffer::Buffer 2 failed - " << err << std::endl;
std::cin.get();
}
err = queue.enqueueWriteBuffer(d_ip, CL_TRUE, 0, W*H*sizeof(float), &my2D[0]);
if(err != CL_SUCCESS) {
std::cout << "Queue::enqueueWriteBuffer failed - " << err << std::endl;
std::cin.get();
}
std::ifstream sourceFileName("so_question.cl");
std::string sourceFile(std::istreambuf_iterator<char>(sourceFileName), (std::istreambuf_iterator<char>()));
Program::Sources rotn_source(1,std::make_pair(sourceFile.c_str(), sourceFile.length() + 1));
Program rotn_program(context, rotn_source, &err);
if(err != CL_SUCCESS) {
std::cout << "Program::Program failed - " << err << std::endl;
std::cin.get();
}
err = rotn_program.build(devices);
if(err != CL_SUCCESS) {
std::cout << "Program::build failed - " << err << std::endl;
std::cin.get();
}
}
Вы заметите, что я добавил намного больше проверок ошибок. Это позволило мне узнать, что звонок Context::Context
фактически сделал сбой в вашей первоначальной программе. Вероятно, проблема заключалась в том, что platforms[1]
не существовало (в векторе было 1 элемент), поэтому я переключил его на platforms[0]
.
Как только это было исправлено, я получил нарушение доступа на вызов queue.enqueueWriteBuffer();
. Проблема заключалась в том, что ваш 2-мерный массив был фактически массивом массивов, распределенных по кучам. Это проблема, потому что OpenCL ожидает, что сможет считывать данные из непрерывной памяти, что не относится к распределению с помощью нового в цикле, как вы это делали. На самом деле не было никакой гарантии, что ваши массивы будут рядом друг с другом в памяти.
Чтобы решить эту задачу, я выделил одномерный массив в стеке (см. Цикл в начале). Вызов затем становится
queue.enqueueWriteBuffer(d_ip, CL_TRUE, 0, W*H*sizeof(float), &my2D[0]);
Однако, вы, вероятно, не будете в состоянии сделать это с 1024 х 1024 массивом float
, потому что вы будете бюстом пространства стека. Если вам нужен массив, который большой, вы, вероятно, захотите new
один одномерный массив, достаточно большой, чтобы содержать ваши данные и выполнять арифметику индекса самостоятельно. Это гарантирует, что вы получите все пространство для хранения как один непрерывный кусок.
Код ошибки в коде CL_BUILD_PROGRAM_FAILURE
на вызов err = rotn_program.build()
, что означает, что в вашем программном коде CL есть ошибка. Поскольку это совершенно другая проблема, я позволю вам понять это.
спасибо, что показал мне, как это сделать. к сожалению, он все еще терпит крах. ----> int e = -1; Программа rotn_program (контекст, rotn_source, &e); \t если (е == CL_SUCCESS) \t \t е = rotn_program.build (устройства);.! – user1873073
@ user1873073 Я обновил свой ответ, дайте мне знать, если это помогло –
еще раз спасибо платформа был установлен на 1 по назначению, но я понятия не имел о других вещах. Что касается ядра, ему не хватало открытия {. – user1873073