В настоящее время работает над реализацией 2D-массива с OpenCL. По большей части все это отлично работает, когда matrix_size меньше 15 или меньше. Когда я увеличиваю его до 100, программа выйдет из строя. Согласно отладчику визуальной студии, проблема представляется целочисленным делением на 0. Я не совсем уверен, где это может произойти. Мое предположение: это проблема с работой повестки и рабочей группе:Внедрение 2D-массива OpenCL
queue.enqueueNDRangeKernel(kernel, cl::NullRange, cl::NDRange(matrix_size*matrix_size), cl::NullRange);
К сожалению, я не совсем уверен, как идти о решении этого. В конечном счете я хочу иметь возможность запускать эти базовые вычисления на относительно больших наборах данных.
int main() {
` srand((unsigned int)time(NULL));
const int matrix_size = 100;
string input;
string func;
string input_file;
cout << "Please enter a arithmetic option: multi or add" << endl;
cout << ">> ";
input_file = "MatrixArithmetic.cl";
getline(cin, input);
if (input[0] == 'a') {func = "matrix_add";}
else if (input[0] == 'm') {func = "matrix_multi";}
else { cout << "Not a valid option... exiting" << endl; return 0; }
ifstream ArithmeticFile(input_file);
string src(istreambuf_iterator<char>(ArithmeticFile), (istreambuf_iterator<char>()));
//prepare platform
vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
auto platform = platforms.front();
//gather device info from platform and store into devices vector
vector<cl::Device> devices;
platform.getDevices(CL_DEVICE_TYPE_GPU, &devices);
//chose device for computation
auto device = devices.front();
cout << "Using device: " << device.getInfo<CL_DEVICE_NAME>() << endl;
/*cout << "This: " << CL_DEVICE_MAX_MEM_ALLOC_SIZE << endl;
cout << "This 2: " << CL_DEVICE_MAX_MEM_ALLOC_SIZE << endl;*/
//setup the context
cl::Program::Sources sources;
sources.push_back({ src.c_str(), src.length() });
cl::Context context(device);
cl::Program program(context, sources);
auto err = program.build("-cl-std=CL1.2");
//setup kernel (this is kernel specific)
cl::Buffer buffer_A(context, CL_MEM_READ_WRITE, sizeof(float)*matrix_size*matrix_size);
cl::Buffer buffer_B(context, CL_MEM_READ_WRITE, sizeof(float)*matrix_size*matrix_size);
cl::Buffer buffer_C(context, CL_MEM_READ_WRITE, sizeof(float)*matrix_size*matrix_size);
//build and seed matrix using random for computation this is done on the main processor
float vec1[matrix_size][matrix_size];
float vec2[matrix_size][matrix_size];
for (int x = 0; x < matrix_size; x++) {
for (int y = 0; y < matrix_size; y++) {
vec1[x][y] = (float)(1+rand()%(rand()%1000));
vec2[x][y] = (float)(1+rand()%(rand()%1000));
}
}
//queue setup for pushing commands to device
cl::CommandQueue queue(context, device);
//write vec1 and vec2 to device
queue.enqueueWriteBuffer(buffer_A, CL_TRUE, 0, sizeof(float)*matrix_size*matrix_size, vec1);
queue.enqueueWriteBuffer(buffer_B, CL_TRUE, 0, sizeof(float)*matrix_size*matrix_size, vec2);
////run the kernel
cl::Kernel kernel = cl::Kernel(program, func.c_str());
//pushing argument to kernel it has 3 total arguments
kernel.setArg(0, buffer_A);
kernel.setArg(1, buffer_B);
kernel.setArg(2, buffer_C);
queue.enqueueNDRangeKernel(kernel, cl::NullRange, cl::NDRange(matrix_size*matrix_size), cl::NullRange);
queue.finish();
//writing to the buffer
float vec3[matrix_size][matrix_size];
queue.enqueueReadBuffer(buffer_C, CL_TRUE, 0, sizeof(float)*matrix_size*matrix_size, vec3);
cin.get();
return 0;
}
Kernel:
__kernel void matrix_add(__global const float *A, __global float *B,
__global float *C)
{
//index of the current element
int x = get_global_id(0);
//operation
C[x] = A[x] + B[x];
}
__kernel void matrix_multi(__global const float *A, __global const float *B, __global float *C)
{
//OpenCL does not take 2D arrays it had to be flatten
//index of the current element
int x = get_global_id(0);
//operation
C[x] = A[x] * B[x];
}
Технические характеристики: i5 4690K и AMD r9 290 8GB Ram. Таким образом, память не должна быть проблемой, каждая «матрица» должна занимать около 4000 байт при размере 100x100