#include "common.h"
const char *shared_sub_buffers_test_kernel[] = {
"typedef struct Node {\n"
" int global_id;\n"
" int position_in_list;\n"
" __global struct Node* pNext;\n"
"} Node;\n"
"__global Node* allocate_node(__global Node* pNodes1, __global Node* pNodes2, volatile __global int* allocation_index, size_t i)\n"
"{\n"
" if(i & 0x1)\n"
" return &pNodes1[atomic_inc(allocation_index)];\n"
" else\n"
" return &pNodes2[atomic_inc(allocation_index)];\n"
"}\n"
"__kernel void create_linked_lists(__global Node* pNodes_sub1, __global Node* pNodes2_sub1, __global Node* pNodes_sub2, __global Node* pNodes2_sub2, volatile __global int* allocation_index, int list_length) \n"
"{\n"
" size_t i = get_global_id(0);\n"
" __global Node *pNode = &pNodes_sub1[i];\n"
" pNode->global_id = i;\n"
" pNode->position_in_list = 0;\n"
" __global Node *pNew;\n"
" for(int j=1; j < list_length; j++) {\n"
" pNew = allocate_node(pNodes_sub1, pNodes2_sub1, allocation_index, i);\n"
" pNew->global_id = i;\n"
" pNew->position_in_list = j;\n"
" pNode->pNext = pNew; // link new node onto end of list\n"
" pNode = pNew; // move to end of list\n"
" }\n"
"}\n"
"__kernel void verify_linked_lists(__global Node* pNodes_sub1, __global Node* pNodes2_sub1, __global Node* pNodes_sub2, __global Node* pNodes2_sub2, volatile __global uint* num_correct, int list_length)\n"
"{\n"
" size_t i = get_global_id(0);\n"
" __global Node *pNode = &pNodes_sub1[i];\n"
" for(int j=0; j < list_length; j++) {\n"
" if( pNode->global_id == i && pNode->position_in_list == j)\n"
" atomic_inc(num_correct);\n"
" else \n"
" break;\n"
" pNode = pNode->pNext;\n"
" }\n"
"}\n"
};
cl_int create_linked_lists_on_host_sb(cl_command_queue cmdq, cl_mem nodes, cl_mem nodes2, cl_int ListLength, size_t numLists )
{
cl_int error = CL_SUCCESS;
log_info("SVM: creating linked list on host ");
Node *pNodes = (Node*) clEnqueueMapBuffer(cmdq, nodes, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(Node)*ListLength*numLists, 0, NULL,NULL, &error);
test_error2(error, pNodes, "clEnqueueMapBuffer failed");
Node *pNodes2 = (Node*) clEnqueueMapBuffer(cmdq, nodes2, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(Node)*ListLength*numLists, 0, NULL,NULL, &error);
test_error2(error, pNodes2, "clEnqueueMapBuffer failed");
create_linked_lists(pNodes, numLists, ListLength);
error = clEnqueueUnmapMemObject(cmdq, nodes, pNodes, 0,NULL,NULL);
test_error(error, "clEnqueueUnmapMemObject failed");
error = clEnqueueUnmapMemObject(cmdq, nodes2, pNodes2, 0,NULL,NULL);
test_error(error, "clEnqueueUnmapMemObject failed");
error = clFinish(cmdq);
test_error(error, "clFinish failed");
return error;
}
cl_int verify_linked_lists_on_host_sb(int ci, cl_command_queue cmdq, cl_mem nodes, cl_mem nodes2, cl_int ListLength, size_t numLists )
{
cl_int error = CL_SUCCESS;
Node *pNodes = (Node*) clEnqueueMapBuffer(cmdq, nodes, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(Node)*ListLength * numLists, 0, NULL,NULL, &error);
test_error2(error, pNodes, "clEnqueueMapBuffer failed");
Node *pNodes2 = (Node*) clEnqueueMapBuffer(cmdq, nodes2, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(Node)*ListLength * numLists, 0, NULL,NULL, &error);
test_error2(error, pNodes, "clEnqueueMapBuffer failed");
error = verify_linked_lists(pNodes, numLists, ListLength);
if(error) return -1;
error = clEnqueueUnmapMemObject(cmdq, nodes, pNodes, 0,NULL,NULL);
test_error(error, "clEnqueueUnmapMemObject failed");
error = clEnqueueUnmapMemObject(cmdq, nodes2, pNodes2, 0,NULL,NULL);
test_error(error, "clEnqueueUnmapMemObject failed");
error = clFinish(cmdq);
test_error(error, "clFinish failed");
return error;
}
int test_svm_shared_sub_buffers(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements)
{
clContextWrapper context = NULL;
clProgramWrapper program = NULL;
cl_uint num_devices = 0;
cl_int error = CL_SUCCESS;
clCommandQueueWrapper queues[MAXQ];
error = create_cl_objects(deviceID, &shared_sub_buffers_test_kernel[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
if(error) return -1;
size_t numLists = num_elements;
if(numLists & 0x1) numLists++;
cl_int ListLength = 32;
clKernelWrapper kernel_create_lists = clCreateKernel(program, "create_linked_lists", &error);
test_error(error, "clCreateKernel failed");
clKernelWrapper kernel_verify_lists = clCreateKernel(program, "verify_linked_lists", &error);
test_error(error, "clCreateKernel failed");
size_t nodes_bufsize = sizeof(Node)*ListLength*numLists;
Node* pNodes = (Node*) clSVMAlloc(context, CL_MEM_READ_WRITE, nodes_bufsize, 0);
Node* pNodes2 = (Node*) clSVMAlloc(context, CL_MEM_READ_WRITE, nodes_bufsize, 0);
{
clMemWrapper nodes = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, nodes_bufsize, pNodes, &error);
test_error(error, "clCreateBuffer failed.");
cl_buffer_region r;
r.origin = 0;
r.size = nodes_bufsize / 2;
clMemWrapper nodes_sb1 = clCreateSubBuffer(nodes, 0, CL_BUFFER_CREATE_TYPE_REGION, (void*)&r, &error);
test_error(error, "clCreateSubBuffer");
r.origin = nodes_bufsize / 2;
clMemWrapper nodes_sb2 = clCreateSubBuffer(nodes, 0, CL_BUFFER_CREATE_TYPE_REGION, (void*)&r, &error);
test_error(error, "clCreateSubBuffer");
clMemWrapper nodes2 = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, sizeof(Node)*ListLength*numLists, pNodes2, &error);
test_error(error, "clCreateBuffer failed.");
r.origin = 0;
r.size = nodes_bufsize / 2;
clMemWrapper nodes2_sb1 = clCreateSubBuffer(nodes2, 0, CL_BUFFER_CREATE_TYPE_REGION, (void*)&r, &error);
test_error(error, "clCreateSubBuffer");
r.origin = nodes_bufsize / 2;
clMemWrapper nodes2_sb2 = clCreateSubBuffer(nodes2, 0, CL_BUFFER_CREATE_TYPE_REGION,(void*)&r, &error);
test_error(error, "clCreateSubBuffer");
clMemWrapper allocator = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_int), NULL, &error);
test_error(error, "clCreateBuffer failed.");
clMemWrapper num_correct = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_int), NULL, &error);
test_error(error, "clCreateBuffer failed.");
error |= clSetKernelArg(kernel_create_lists, 0, sizeof(void*), (void *) &nodes_sb1);
error |= clSetKernelArg(kernel_create_lists, 1, sizeof(void*), (void *) &nodes2_sb1);
error |= clSetKernelArg(kernel_create_lists, 2, sizeof(void*), (void *) &nodes_sb2);
error |= clSetKernelArg(kernel_create_lists, 3, sizeof(void*), (void *) &nodes2_sb2);
error |= clSetKernelArg(kernel_create_lists, 4, sizeof(void*), (void *) &allocator);
error |= clSetKernelArg(kernel_create_lists, 5, sizeof(cl_int),(void *) &ListLength);
error |= clSetKernelArg(kernel_verify_lists, 0, sizeof(void*), (void *) &nodes_sb1);
error |= clSetKernelArg(kernel_verify_lists, 1, sizeof(void*), (void *) &nodes2_sb1);
error |= clSetKernelArg(kernel_verify_lists, 2, sizeof(void*), (void *) &nodes_sb2);
error |= clSetKernelArg(kernel_verify_lists, 3, sizeof(void*), (void *) &nodes2_sb2);
error |= clSetKernelArg(kernel_verify_lists, 4, sizeof(void*), (void *) &num_correct);
error |= clSetKernelArg(kernel_verify_lists, 5, sizeof(cl_int),(void *) &ListLength);
test_error(error, "clSetKernelArg failed");
for (int ci=0; ci<(int)num_devices+1; ci++)
{
for (int vi=0; vi<(int)num_devices+1; vi++)
{
if(ci == num_devices)
{
error = create_linked_lists_on_host_sb(queues[0], nodes, nodes2, ListLength, numLists);
if(error) return -1;
}
else
{
error = create_linked_lists_on_device(ci, queues[ci], allocator, kernel_create_lists, numLists);
if(error) return -1;
}
if(vi == num_devices)
{
error = verify_linked_lists_on_host_sb(vi, queues[0], nodes, nodes2, ListLength, numLists);
if(error) return -1;
}
else
{
error = verify_linked_lists_on_device(vi, queues[vi], num_correct, kernel_verify_lists, ListLength, numLists);
if(error) return -1;
}
}
}
}
clSVMFree(context, pNodes2);
clSVMFree(context, pNodes);
return 0;
}