I'm trying to implement a variation of the Dining Philosophers problem using OpenCL. I have posted the code below but it's not giving the expected output. I'm using a semaphore array for the chopsticks and based on whether a Philosopher is using a pair of chopsticks, the value might be one or zero(or in this variation CLEAN or DIRTY).
Tried using atomic exchange for the core algorithm.
Kernel Code: .cl file
#pragma OPENCL EXTENSION cl_khr_global_int64_base_atomics : enable
#pragma OPENCL EXTENSION cl_khr_local_int64_base_atomics : enable
#pragma OPENCL EXTENSION cl_khr_global_int64_extended_atomics : enable
#pragma OPENCL EXTENSION cl_khr_local_int64_extended_atomics : enable
void GetSem(__global int * sem)
{
int occupied = atom_xchg(sem, 1);
while(occupied > 0)
printf("\n hung \n");
occupied = atom_xchg(sem, 1);
}
void ReleaseSem(__global int * sem)
{
int prevVal = atom_xchg(sem, 0);
}
__kernel void dine(__global int * semaphor)
{
printf("\n kernel exec \n");
int i = get_global_id(0);
printf("\n %d \n",semaphor[i]);
GetSem(&semaphor[i%5]);
GetSem(&semaphor[(i+1)%5]);
printf("\n stuck \n");
int a=(i%5)+1;
int b=((i+1)%5)+1;
printf("Philoshper %d has %d and %d Chop Sticks.\n",i+1,a,b);
ReleaseSem(&semaphor[(i+1)%5]);
ReleaseSem(&semaphor[i%5]);
printf("\n done \n");
}
I have initialised the semaphore array to 0 in the host code. The global work size that I'm using is 5 and the local work size is 1.
Here's the host code (.c file) for reference:
#include <OpenCL/opencl.h>
#include<stdio.h>
#include<stdlib.h>
#define MAX_SOURCE_SIZE (0x100000)
int main(void) {
FILE *fp;
char *source_str;
size_t source_size;
int i;
#pragma OPENCL EXTENSION cl_amd_printf:enable
fp = fopen("dine.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);
// printf("\n********************Source code is*****************\n %s \n********************end************* ",source_str);
fclose( fp );
char *info;
cl_uint infoSize;
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);
// clGetPlatformInfo(platform_id,CL_PLATFORM_NAME,0, NULL, &infoSize);
info=(char *)malloc(sizeof(char)*infoSize);
clGetPlatformInfo(platform_id,CL_PLATFORM_NAME,infoSize, info, NULL);
ret = clGetDeviceIDs( platform_id, CL_DEVICE_TYPE_ALL, 1,
&device_id, &ret_num_devices);
//printf("Number of platforms %d and number of devices are %d",ret_num_platforms,ret_num_devices);
//printf("\n Device Propoerties are %s",info);
cl_context context = clCreateContext( NULL, 1, &device_id, NULL, NULL, &ret);
// Create a command queue
cl_command_queue command_queue = clCreateCommandQueue(context, device_id, 0, &ret);
// Create memory buffers on the device for each vector
cl_mem c_mem_obj = clCreateBuffer(context, CL_MEM_READ_ONLY , sizeof(int)*5, NULL, &ret);
int *C = (int *)malloc(sizeof(int)*5);
for(i=0;i<5;i++)
{
C[i]=0;
}
clEnqueueWriteBuffer(command_queue, c_mem_obj, CL_TRUE, 0,
sizeof(int)*5 , C, 0, NULL, NULL);
cl_program program = clCreateProgramWithSource(context, 1,
(const char **)&source_str, (const size_t *)&source_size, &ret);
// Build the program
ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);
// Create the OpenCL kernel
cl_kernel kernel = clCreateKernel(program, "dine", &ret);
ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&c_mem_obj);
// Execute the OpenCL kernel on the list
size_t global_item_size = 5; // Process the entire lists
size_t local_item_size = 1; // Process in groups of 64
ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_item_size, &local_item_size, 0, NULL, NULL);
printf("Return code is %d\n",ret);
}
Expected result: The program should keep running as long as the user desires and it should keep showing the state of the Philosophers who are eating.
Actual results: Random output every time the code is exec.
1) OP: Return code is 0
kernel exec
2) OP: Return code is 0
kernel exec
0