Я пытаюсь изучить основы OpenCL.
Я думал, что этот код в ядре:
out[ 1 & ((a+b)==(b+a)) ] = (char)1;
Будет генерировать те же результаты, что и:
out[ 1 ] = (char)1;
Может ли кто-нибудь сказать мне, почему он генерирует другой результат?
Вот полный исходный код моего ядра:
#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable
__kernel void hello(__global char * out)
{
size_t tid = get_global_id(0);
int a = tid & 0xff;
int b = (tid >> 8) & 0xff;
out[ 1 & ((a+b)==(b+a)) ] = (char)1;
}
Если я заменю этот последний оператор на «out[1]=(char)1;» тогда "out[0]" не будет записано. Но приведенное выше ядро запишет «1» в out[0].
РЕДАКТИРОВАТЬ: это мой код на С++:
#include <utility>
#define __NO_STD_VECTOR // Use cl::vector instead of STL version
#include <CL/cl.hpp>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include <iterator>
inline void checkErr(cl_int err, const char * name)
{
if (err != CL_SUCCESS) {
std::cerr << "ERROR: " << name
<< " (" << err << ")" << std::endl;
std::exit(EXIT_FAILURE);
}
}
int main()
{
cl_int err;
cl::vector< cl::Platform > platformList;
cl::Platform::get(&platformList);
checkErr(platformList.size()!=0 ? CL_SUCCESS : -1, "cl::Platform::get");
std::cerr << "Platform number is: " << platformList.size() << std::endl;
std::string platformVendor;
platformList[0].getInfo((cl_platform_info)CL_PLATFORM_VENDOR, &platformVendor);
std::cerr << "Platform is by: " << platformVendor << "\n";
cl_context_properties cprops[3] =
{CL_CONTEXT_PLATFORM, (cl_context_properties)(platformList[0])(), 0};
cl::Context context(
CL_DEVICE_TYPE_GPU,
cprops,
NULL,
NULL,
&err);
checkErr(err, "Conext::Context()");
unsigned char outH[2] = {0};
cl::Buffer outCL(
context,
CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR,
sizeof(outH),
outH,
&err);
checkErr(err, "Buffer::Buffer()");
cl::vector<cl::Device> devices;
devices = context.getInfo<CL_CONTEXT_DEVICES>();
checkErr(
devices.size() > 0 ? CL_SUCCESS : -1, "devices.size() > 0");
std::ifstream file("condition1.cl");
checkErr(file.is_open() ? CL_SUCCESS:-1, "condition1.cl");
const std::string prog(std::istreambuf_iterator<char>(file), (std::istreambuf_iterator<char>()));
cl::Program::Sources source(1, std::make_pair(prog.c_str(), prog.length()+1));
cl::Program program(context, source);
err = program.build(devices,"");
checkErr(err, "Program::build()");
cl::Kernel kernel(program, "hello", &err);
checkErr(err, "Kernel::Kernel()");
err = kernel.setArg(0, outCL);
checkErr(err, "Kernel::setArg()");
cl::CommandQueue queue(context, devices[0], 0, &err);
checkErr(err, "CommandQueue::CommandQueue()");
cl::Event event;
err = queue.enqueueNDRangeKernel(
kernel,
cl::NullRange,
cl::NDRange(65536),
cl::NDRange(1, 1),
NULL,
&event);
checkErr(err, "ComamndQueue::enqueueNDRangeKernel()");
event.wait();
err = queue.enqueueReadBuffer(
outCL,
CL_TRUE,
0,
sizeof(outH),
outH);
checkErr(err, "ComamndQueue::enqueueReadBuffer()");
for (int i = 0; i < sizeof(outH); i++)
std::cout << (int)outH[i] << " ";
std::string str;
std::getline(std::cin, str);
return EXIT_SUCCESS;
}
РЕДАКТИРОВАТЬ2:
По крайней мере, это не вызвано "неопределенным поведением". Я также получаю странные результаты для этого кода ядра:
char result = 0;
for (int a = 0; a < 2; a++) {
for (int b = 0; b < 2; b++) {
if ((a+b) != (b+a))
result |= (1 << (a+2*b));
}
}
Я ожидаю, что «результат» получит значение 0. Но он получает значение 6. Если я изменю != на ==, тогда результат получит значение 9. Итак, в этом коде, когда «а» не равно "b", то (a+b) не равно (b+a).
Если я изменю код и установлю известное значение для «a» или «b», результат будет равен 0, как я и ожидал. Например:
char result = 0;
int a = 1;
/*for (int a = 0; a < 2; a++)*/ {
for (int b = 0; b < 2; b++) {
if ((a+b) != (b+a))
result |= (1 << (a+2*b));
}
}
enqueueNDRangeKernel
? - person Fabien R   schedule 12.01.2013uchar
может быть проблемой (даже если у вас включено расширение) - person Tom Fenech   schedule 06.11.2013