алгоритм шифрования vigenere в c с OpenCL не работает должным образом - PullRequest
1 голос
/ 28 мая 2020

Я пытаюсь сделать алгоритм шифрования Vigenere в c с OpenCL, у меня нет опыта работы с OpenCL. Я использую ma c os (так что использую OpenCL 1.2 или 1.1) и создаю программу с помощью Makefile. Файл скомпилирован, но результат не такой, как я ожидал.

  1. пример текущей проблемы:

    • Входное сообщение: testingviegere
    • Ключ ввода: ключ
    • Выходное сообщение: UUUUUUUUUUUUUUU
  2. ожидаемый:

    • Входное сообщение: testingviegere
    • Ключ ввода: ключ
    • Выходное сообщение: diqdmlqzgokcbi

Если кто-нибудь скажет мне, что я делаю неправильно, я буду очень благодарен.

Это мой c код:

#include <stdio.h>
#include <stdlib.h>
#include <OpenCL/opencl.h>

#define CL_USE_DEPRECATED_OPENCL_1_2_APIS

#define MY_CL_GPU 1
#define MY_CL_CPU 0

#define ENCRYPT 'E'
#define DECRYPT 'D'

#define IO_MESAGE
#define IO_KEY

#define MAX_SOURCE_SIZE (0x100000)

void IO_selected_mode( char* program_opreation );
int IO_get_mesage( char* mesage );
void normalize_key( char* key, int key_size, int mesage_size );

int main(){

    //int compute_unit = MY_CL_CPU;
    int compute_unit = MY_CL_GPU;

    char name[128];
    dispatch_queue_t queue;

    if ( compute_unit == MY_CL_GPU ){
        queue = gcl_create_dispatch_queue(CL_DEVICE_TYPE_GPU, NULL);
    }else{
        queue = gcl_create_dispatch_queue(CL_DEVICE_TYPE_CPU, NULL);
    }

    if ( queue == NULL )
    {
        printf("\nCan't find OpenCL  copute unit");
    }

    cl_device_id device_id = gcl_get_device_id_with_dispatch_queue(queue);
    clGetDeviceInfo( device_id, CL_DEVICE_NAME, 128, name, NULL);
    printf("Created a dispatch queue using the %s\n\n", name);

    char program_opreation = '0';
    IO_selected_mode( &program_opreation );


    printf("\nInput mesage:");
    char* mesage = NULL;// = malloc( 100 * sizeof(char) ) ;
    int mesage_size;
    mesage_size = IO_get_mesage( mesage );

    printf("\nInput key:");
    char* key = NULL;// = malloc( 100 * sizeof(char) ) ;
    int key_size; 
    key_size = IO_get_mesage( key );
    normalize_key( key, key_size, mesage_size );

    char* output;
    int output_size;
    output = malloc( mesage_size * sizeof(char) );
    output_size = mesage_size;

    int mesage_data_size = mesage_size * sizeof(char);


    FILE* fp;
    char* source_str;
    size_t source_size;

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

    cl_int ret; 

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

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

    cl_mem mesage_mem_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, mesage_data_size, NULL, &ret);
    cl_mem key_mem_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, mesage_data_size, NULL, &ret);
    cl_mem output_mem_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, mesage_data_size, NULL, &ret);

    // Copy the lists A and B to their respective memory buffers
    ret = clEnqueueWriteBuffer(command_queue, mesage_mem_obj, CL_TRUE, 0, mesage_data_size, mesage, 0, NULL, NULL);
    ret = clEnqueueWriteBuffer(command_queue, key_mem_obj, CL_TRUE, 0, mesage_data_size, key, 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;

    if( program_opreation == ENCRYPT )
    {
        kernel = clCreateKernel(program, "Encrypt_module", &ret);
    }
    if( program_opreation == DECRYPT )
    {
        kernel = clCreateKernel(program, "Decrypt_module", &ret);
    }

    ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void*)&mesage_mem_obj);
    ret = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void*)&key_mem_obj);
    ret = clSetKernelArg(kernel, 2, sizeof(cl_mem), (void*)&output_mem_obj);

    size_t global_item_size[1];
    global_item_size[0] = mesage_size;
    ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, global_item_size, NULL, 0, NULL, NULL);

    ret = clEnqueueReadBuffer(command_queue, output_mem_obj, CL_TRUE, 0, output_size, output, 0, NULL, NULL);



    if( program_opreation == ENCRYPT )
    {
        printf("\nThe Encrypted mesage is:\n>>>%s\n", output);
    }
    else if( program_opreation == DECRYPT )
    {
        printf("\nThe Decrypted mesage is:\n>>>%s\n", output);
    }

    return 0;
}

void IO_selected_mode( char* program_opreation ){
    printf("\nSelect mode: for Encryption press 'E' ; for Decription press D \n>>>");
    scanf( "%c", program_opreation );
}

int IO_get_mesage( char* mesage ){

    mesage = malloc( sizeof(char) );
    char c = 'a';
    int size = 0;
    printf("\n>>>");
    getc(stdin); //Posibil BUG

    while( c != '\n' ){
        size++;

        c = getc( stdin );

        mesage = (char*)realloc( mesage, size * sizeof(char) );
        mesage[ size ] = c;
    }

    return size ;
}


void normalize_key( char* key, int key_size, int mesage_size ){

    key = (char*)realloc( key, mesage_size * sizeof(char) );

    int i, j;

    for( i = 0, j = 0; i < mesage_size; i++, j++ ){
        if(j == key_size - 1 )
            j = 0;

        key[i] = key[j];
    }
}

Это мой код ядра:

    __kernel void Encrypt_module(__global const char* mesage, __global const char* key, __global char* encrypted_message)
{
    int i = get_global_id(0); 
    int mesage_size = get_global_size(0);

    char key_inter = key[i] - 'a';
    char mesage_inter = encrypted_message[i] - 'a';

    if( mesage[i] == ' ' )
    {
        encrypted_message[i]=mesage[i];
    }
    else
    {
        mesage_inter = ( mesage_inter + key_inter ) % 26;
        encrypted_message[i] = mesage_inter + 'a';
    }

}

__kernel void Decrypt_module(__global const char* encrypted_message, __global const char* key, __global int* decrypted_message)
{
    int i = get_global_id(0); 
    int mesage_size = get_global_size(0);

    if( encrypted_message[i] == ' ' )
    {
        decrypted_message[i] = encrypted_message[i];
    }
    else
    {
        decrypted_message[i] = ( ( encrypted_message[i] - key[i] + 26 ) % 26 ) + 'a';
    }

}

Это мой Makefile:

OPENCLC=/System/Library/Frameworks/OpenCL.framework/Libraries/openclc
BUILD_DIR=./build
EXECUTABLE=main
.SUFFIXES:
KERNEL_ARCH=i386 x86_64 gpu_32 gpu_64
BITCODES=$(patsubst %, mykernel.cl.%.bc, $(KERNEL_ARCH))

$(EXECUTABLE): $(BUILD_DIR)/mykernel.cl.o $(BUILD_DIR)/main.o $(BITCODES)
    clang -framework OpenCL -o $@ $(BUILD_DIR)/mykernel.cl.o $(BUILD_DIR)/main.o

$(BUILD_DIR)/mykernel.cl.o: mykernel.cl.c
    mkdir -p $(BUILD_DIR)
    clang -c -Os -Wall -arch x86_64 -o $@ -c mykernel.cl.c

$(BUILD_DIR)/main.o: main.c mykernel.cl.h
    mkdir -p $(BUILD_DIR)
    clang -c -Os -Wall -arch x86_64 -o $@ -c $<

mykernel.cl.c mykernel.cl.h: mykernel.cl
    $(OPENCLC) -x cl -cl-std=CL1.1 -cl-auto-vectorize-enable -emit-gcl $<

mykernel.cl.%.bc: mykernel.cl
    $(OPENCLC) -x cl -cl-std=CL1.1 -Os -arch $* -emit-llvm -o $@ -c $<

.PHONY: clean
clean:
    rm -rf $(BUILD_DIR) mykernel.cl.h mykernel.cl.c $(EXECUTABLE) *.bc

run:
    ./main
...