قم بإصلاح المخطط التفصيلي لبرنامج opencl وربما البرنامج نفسه


إنشاء برنامج باستخدام OpenCL واستخدام الذاكرة المحلية. المهمة: ب=دقيقة(أ+ج)

لدي رسم تخطيطي جاهز، لكن المعلم يقول إنه يظهر كل شيء بالتسلسل، ولدينا برنامج موازي ولا أعرف كيفية إصلاح المخطط الهيكلي.

أريد أيضًا معرفة ما إذا كنت قد كتبت برنامجًا باستخدام الذاكرة المحلية بشكل صحيح أم لا.

رابط الصورة مع مخطط الكتلة: https://www.imghippo.com/i/1704956923.jpg

#define _CRT_SECURE_NO_WARNINGS
#define CL_USE_DEPRECATED_OPENCL_1_2_APIS
#include <CL/cl.h>
#include <CL/cl_platform.h>
#include <iostream>
#include <cstdlib>
#include <stdio.h>

#define MAX_SOURCE_SIZE (0x100000)
#define LIST_SIZE 64

int main(void) {
    int* A = new int[LIST_SIZE];
    int* C = new int[LIST_SIZE];
    int* B = new int[LIST_SIZE];
    srand(time(0));
    for (int i = 0; i < LIST_SIZE; i++) {
        A[i] = (rand() % 200) / 2.;
        C[i] = (rand() % 200) / 2.;
    }

    FILE* fp;
    char* source_str;
    size_t source_size;

    fp = fopen("kernel.cl", "r");
    if (!fp) {
        fprintf(stderr, "Failed to load kernel.\n");
        exit(1);
    }
    source_str = new char[MAX_SOURCE_SIZE];
    source_size = fread(source_str, 1, MAX_SOURCE_SIZE, fp);
    fclose(fp);

    cl_platform_id platform_id = NULL;
    cl_device_id device_id = NULL;
    cl_uint ret_num_devices;
    cl_uint ret_num_platforms;
    cl_int ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms);
    ret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_DEFAULT, 1, &device_id, &ret_num_devices);

    cl_context context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret);

    cl_command_queue command_queue = clCreateCommandQueueWithProperties(context, device_id, 0, &ret);

    cl_mem a_mem_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, LIST_SIZE * sizeof(int), NULL, &ret);
    cl_mem c_mem_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, LIST_SIZE * sizeof(int), NULL, &ret);
    cl_mem b_mem_obj = clCreateBuffer(context, CL_MEM_WRITE_ONLY, LIST_SIZE * sizeof(int), NULL, &ret);

    ret = clEnqueueWriteBuffer(command_queue, a_mem_obj, CL_TRUE, 0, LIST_SIZE * sizeof(int), A, 0, NULL, NULL);
    ret = clEnqueueWriteBuffer(command_queue, c_mem_obj, CL_TRUE, 0, LIST_SIZE * sizeof(int), C, 0, NULL, NULL);

    cl_program program = clCreateProgramWithSource(context, 1, (const char**)&source_str, (const size_t*)&source_size, &ret);

    ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);

    cl_kernel kernel = clCreateKernel(program, "krn", &ret);

    size_t local_item_size = 64;
    ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void*)&a_mem_obj);
    ret = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void*)&c_mem_obj);
    ret = clSetKernelArg(kernel, 2, sizeof(cl_mem), (void*)&b_mem_obj);
    ret = clSetKernelArg(kernel, 3, local_item_size * sizeof(int), NULL);

    size_t global_item_size = LIST_SIZE;
    ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_item_size, &local_item_size, 0, NULL, NULL);

    ret = clEnqueueReadBuffer(command_queue, b_mem_obj, CL_TRUE, 0, LIST_SIZE * sizeof(int), B, 0, NULL, NULL);

    for (int i = 0; i < LIST_SIZE; i++) {
        printf("%d. sum: %d\n", i, B[i]);
    }

    int min = B[0];
    int minIndex = 0;
    for (int i = 0; i < LIST_SIZE; i++) {
        if (B[i] < min) {
            min = B[i];
            minIndex = i;
        }
    }
    printf("\n\n%d. Minimum min(A+C) = %d\n", minIndex, min);

    ret = clFlush(command_queue);
    ret = clFinish(command_queue);
    ret = clReleaseKernel(kernel);
    ret = clReleaseProgram(program);
    ret = clReleaseMemObject(a_mem_obj);
    ret = clReleaseMemObject(c_mem_obj);
    ret = clReleaseMemObject(b_mem_obj);
    ret = clReleaseCommandQueue(command_queue);
    ret = clReleaseContext(context);
    delete[] source_str;
    delete[] A;
    delete[] B;
    delete[] C;
    return 0;
}

kernel.cl:

__kernel void krn(__global const int* A, __global const int* C, __global int* B) {
    int i = get_global_id(0); 
    __local int localA[128];
    __local int localC[128];
    localA[i] = A[i];
    localC[i] = C[i];
    barrier(CLK_LOCAL_MEM_FENCE);
    B[i] = localA[i] + localC[i];
}

ما حاولت:

قام بعمل مخطط بياني خاطئ وكتب برنامجًا

الحل 1

أ. لا.

هذا ليس رسمًا تخطيطيًا لكيفية عمل تطبيقك: إنه مزيج من تطبيق وتعليمات لإنتاجه – وإذا كانت مهمتك تريد منك إنتاج تطبيق متوازي، فأنت بحاجة إلى فحص المهمة بعناية وتحديد الأجزاء التي يمكن أن تكون يتم إجراؤه في وقت واحد وبشكل مستقل، وهو ما لا يغطيه المخطط الحالي على الإطلاق.

بصدق؟ سأقوم بإلغاء كل ما قمت به حتى الآن، وأبدأ من جديد بسجل فارغ، وأعيد قراءة ملاحظات / مواد الدورة التدريبية الخاصة بك من البداية، لأنه يبدو أنك لم تفهم الكثير حتى الآن. ومن المهم جدًا أن تفهم الفرق بين التسلسلي والمتوازي، وحتى بين التطبيق وعملية إنشاء التطبيق – فهما ليسا نفس الشيء.

لا تتعجل في البرمجة: فكر أولاً وستوفر على نفسك الكثير من الوقت الضائع.

コメント

タイトルとURLをコピーしました