Sửa sơ đồ khối của chương trình opencl và có thể cả chính chương trình đó

lập trình


Soạn chương trình bằng OpenCL và sử dụng bộ nhớ cục bộ. Nhiệm vụ: b=min(A+C)

Mình có sơ đồ khối làm sẵn nhưng thầy bảo nó hiển thị mọi thứ một cách tuần tự, chúng ta có chương trình song song mà mình không biết cách sửa sơ đồ khối.

Tôi cũng muốn biết liệu tôi đã viết chương trình sử dụng bộ nhớ cục bộ một cách chính xác hay chưa.

Link ảnh kèm sơ đồ khối: 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];
}

Những gì tôi đã thử:

Viết sai sơ đồ khối và viết chương trình

Giải pháp 1

A. Không.

Đó không phải là sơ đồ về cách ứng dụng của bạn hoạt động: đó là sự kết hợp của một ứng dụng và hướng dẫn để tạo ra ứng dụng đó – và nếu bài tập của bạn muốn bạn tạo một ứng dụng dựa trên song song thì bạn cần phải kiểm tra bài tập một cách cẩn thận và xác định những phần nào có thể được thực hiện được thực hiện đồng thời và độc lập, điều mà sơ đồ hiện tại không đề cập đến.

Thành thật? Tôi sẽ loại bỏ mọi thứ bạn đã làm cho đến nay, bắt đầu lại với một bảng trống và đọc lại các ghi chú/tài liệu khóa học của bạn từ đầu, bởi vì cho đến nay bạn dường như chưa nắm bắt được nhiều. Và điều khá quan trọng là bạn phải hiểu sự khác biệt w=giữa nối tiếp và song song, thậm chí giữa một ứng dụng và hành động tạo ứng dụng – chúng không giống nhau.

Đừng vội viết mã: hãy suy nghĩ trước và bạn sẽ tiết kiệm được rất nhiều thời gian lãng phí.

コメント

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