2016-11-21 5 views
0

В настоящее время работает над реализацией 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

ответ

0

Преступники: rand()% 1000 оценивается равным 0.

vec1[x][y] = (float)(1+rand()%(1+rand()%1000)); 
vec2[x][y] = (float)(1+rand()%(1+rand()%1000)); 

Изменить на:

vec1[x][y] = (float)(1+rand()%(1+rand()%1000)); 
vec2[x][y] = (float)(1+rand()%(1+rand()%1000)); 
0

Вы должны обработать массив 1-D (или выделения) в виде массива 2-D с помощью обертку:

MDArr buf = new MDArr(100,100); // allocates 10k memory and gets its pointer 
buf[10][90]=3; // this is overloaded operator usage for host-side 
clEnqueueWriteBuffer(.,..,buf.ptr()) // 0th addreess of contiguous mem 
            // same as &vec1[0][0] 

так Безразлично» t доступ к несмежным запрещенным зонам.

Редактировать: 100x100 поплавок массива должен быть 4 * 100 * 100 = 40k область памяти для x86 cpu