我正在尝试使用 OpenCL 在 c 中制作 vigenere 加密算法,我没有 OpenCL 经验。我正在使用 mac os(所以我正在运行 OpenCL 1.2 或 1.1)并使用 Makefile 构建程序。该文件已编译,但输出不是我所期望的。
当前问题的示例:
- 输入信息:testviegere
- 输入键:键
- 输出信息:UUUUUUUUUUUUUUU
预期:
- 输入信息:testviegere
- 输入键:键
- 输出信息: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