Я принял программирование OpenCL как часть университетского проекта, и у меня есть небольшая проблема, когда я пытаюсь ввести данные в буферный объект во время процедуры clCreateBuffer().OpenCL clCreateBuffer() сбой программы
Программа представляет собой простое двумерное матричное дополнение. Код выглядит следующим образом:
#define _CRT_SECURE_NO_WARNINGS
#define PROGRAM_FILE "add_kernel.cl"
#define ADD_FUNC "add_matrix"
#define MATRIX_DIM 256
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef MAC
#include <OpenCL/cl.h>
#else
#include <CL/cl.h>
#endif
/* Find a GPU associated with the first available platform */
cl_device_id create_device() {
cl_platform_id platform;
cl_device_id dev;
int err;
/* Identify a platform */
err = clGetPlatformIDs(1, &platform, NULL);
if(err < 0) {
perror("Couldn't identify a platform");
exit(1);
}
/* Access a GPU */
err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &dev, NULL);
if(err < 0) {
perror("Couldn't access any GPU type");
exit(1);
}
return dev;
}
cl_program build_program(cl_context ctx, cl_device_id dev, const char* filename) {
cl_program program;
FILE *program_handle;
char *program_buffer, *program_log;
size_t program_size, log_size;
int err;
/* Read program file and place content into buffer */
program_handle = fopen(filename, "r");
if(program_handle == NULL) {
perror("Couldn't find the program file");
exit(1);
}
fseek(program_handle, 0, SEEK_END);
program_size = ftell(program_handle);
rewind(program_handle);
program_buffer = (char*)malloc(program_size + 1);
program_buffer[program_size] = '\0';
fread(program_buffer, sizeof(char), program_size, program_handle);
fclose(program_handle);
/* Create program from file */
program = clCreateProgramWithSource(ctx, 1,
(const char**)&program_buffer, &program_size, &err);
if(err < 0) {
perror("Couldn't create the program");
exit(1);
}
free(program_buffer);
/* Build program */
err = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
if(err < 0) {
/* Find size of log and print to std output */
clGetProgramBuildInfo(program, dev, CL_PROGRAM_BUILD_LOG,
0, NULL, &log_size);
program_log = (char*) malloc(log_size + 1);
program_log[log_size] = '\0';
clGetProgramBuildInfo(program, dev, CL_PROGRAM_BUILD_LOG,
log_size + 1, program_log, NULL);
printf("%s\n", program_log);
free(program_log);
exit(1);
}
return program;
}
int main(){
/* Host/device data structures */
cl_device_id device;
cl_context context;
cl_command_queue queue;
cl_program program;
cl_kernel add_kernel;
size_t global_size;
cl_ulong mem_size;
cl_int i, j, err, check;
/* Data and buffers */
cl_uint matrix_dim;
float a_mat[MATRIX_DIM][MATRIX_DIM], b_mat[MATRIX_DIM][MATRIX_DIM],
c_mat[MATRIX_DIM][MATRIX_DIM], check_mat[MATRIX_DIM][MATRIX_DIM];
cl_mem a_buffer, b_buffer, c_buffer;
/* Initialize A, B, and check matrices */
srand((unsigned int)time(0));
for(i=0; i<MATRIX_DIM; i++) {
for(j=0; j<MATRIX_DIM; j++) {
a_mat[i][j] = (float)rand()/RAND_MAX;
}
}
srand((unsigned int)time(0));
for(i=0; i<MATRIX_DIM; i++) {
for(j=0; j<MATRIX_DIM; j++) {
b_mat[i][j] = (float)rand()/RAND_MAX;
check_mat[i][j] = 0.0f;
}
}
for(i=0; i<MATRIX_DIM; i++) {
for(j=0; j<MATRIX_DIM; j++) {
check_mat[i][j] += a_mat[i][j] + b_mat[i][j];
}
}
/* Create a device and context */
device = create_device();
context = clCreateContext(NULL, 1, &device, NULL, NULL, &err);
if(err < 0) {
perror("Couldn't create a context");
exit(1);
}
/* Build the program */
program = build_program(context, device, PROGRAM_FILE);
add_kernel = clCreateKernel(program, ADD_FUNC, &err);
if(err < 0) {
perror("Couldn't create a kernel");
exit(1);
};
/* Create buffers */
a_buffer = clCreateBuffer(context,
CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
sizeof(a_mat), a_mat, &err);
if(err < 0) {
perror("Couldn't create buffer A");
exit(1);
};
b_buffer = clCreateBuffer(context,
CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
sizeof(b_mat), b_mat, &err);
if(err < 0) {
perror("Couldn't create buffer B");
exit(1);
};
c_buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY,
sizeof(c_mat), NULL, &err);
if(err < 0) {
perror("Couldn't create buffer C");
exit(1);
};
/* Create a command queue */
queue = clCreateCommandQueue(context, device, 0, &err);
if(err < 0) {
perror("Couldn't create a command queue");
exit(1);
};
/* Create arguments for multiplication kernel */
err = clSetKernelArg(add_kernel, 0, sizeof(a_buffer), &a_buffer);
err |= clSetKernelArg(add_kernel, 1, sizeof(b_buffer), &b_buffer);
err |= clSetKernelArg(add_kernel, 2, sizeof(c_buffer), &c_buffer);
global_size = MATRIX_DIM * MATRIX_DIM;
//printf("%lu\n", global_size);
err = clEnqueueNDRangeKernel(queue, add_kernel, 1, NULL, &global_size,
NULL, 0, NULL, NULL);
if(err < 0) {
perror("Couldn't enqueue the addition kernel");
exit(1);
}
/* Read output buffer */
err = clEnqueueReadBuffer(queue, c_buffer, CL_TRUE, 0,
sizeof(c_mat), c_mat, 0, NULL, NULL);
if(err < 0) {
perror("Couldn't read the buffer");
exit(1);
}
/* Check result */
check = 1;
for(i=0; i<MATRIX_DIM; i++) {
for(j=0; j<MATRIX_DIM; j++) {
if(c_mat[i][j] != check_mat[i][j]){
check = 0;
break;
}
}
}
if(check)
printf("Addition check succeeded.\n");
else
printf("Addition check failed.\n");
/* Deallocate resources */
clReleaseMemObject(a_buffer);
clReleaseMemObject(b_buffer);
clReleaseMemObject(c_buffer);
clReleaseKernel(add_kernel);
clReleaseCommandQueue(queue);
clReleaseProgram(program);
clReleaseContext(context);
return 0;
}
код ядра является следующее:
__kernel void add_matrix(__global float* matrix_a,
__global float* matrix_b,
__global float* result) {
int i = get_global_id(0);
result[i] = matrix_a[i] + matrix_b[i];
}
Теперь он работает отлично подходит для размеров до 358x358, но как только я поставил 359 в MATRIX_DIM он выходит из строя , Он показывает, что обычный «foo.exe перестает работать». Я знаю, что он должен что-то сделать с помощью команды clCreateBuffer(), потому что, если я удалю код из первого clCreateBuffer() и ниже, он запускается и заканчивается нормально, но как только я добавляю еще один, он сбой.
Параметр CL_DEVICE_MAX_MEM_ALLOC_SIZE показывает количество 512 МБ доступной памяти, а данные, которые я пытаюсь передать, намного меньше.
Есть ли что-нибудь, что я могу сделать, чтобы увеличить количество данных, которые я могу обработать?
Мой GPU является Radeon Sapphire HD5770
EDIT: После того, как предложение в комментариях, я побежал отладчик показал следующее сообщение:
Program received signal SIGSEGV, Segmentation fault.
In amdocl!_aclHsaLoader() (C:\WINDOWS\SysWOW64\amdocl.dll)
#15 0x00401355 in create_device() at C:\test\testcl.c:26
C:\test\testcl.c:26:503:beg:0x401355
Я действительно не знаю, что это означает, что, хотя. Есть идеи?
Вы использовали отладчик, чтобы убедиться, что clCreateBuffer является то, что выходит из строя? – immibis
@immibis Я использовал отладчик, и вы были правы, проблема в том, что проблема заключается в create_device() в строке 26. Вот данные: Программный сигнал SIGSEGV, ошибка сегментации. В amdocl! _aclHsaLoader() (C: \ WINDOWS \ SysWOW64 \ amdocl.dll) # 15 0x00401355 в create_device() в C: \ test \ testcl.c: 26 C: \ test \ testcl.c: 26: 503: beg: 0x401355 – kmentis