Initial open source release of OpenCL 2.2 CTS.

This commit is contained in:
Kedar Patil
2017-05-16 18:25:37 +05:30
parent 6911ba5116
commit 2821bf1323
1035 changed files with 343518 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
set(MODULE_NAME multiples)
set(${MODULE_NAME}_SOURCES
main.c
test_multiple_contexts.c
test_multiple_devices.cpp
../../test_common/harness/errorHelpers.c
../../test_common/harness/threadTesting.c
../../test_common/harness/testHarness.c
../../test_common/harness/kernelHelpers.c
../../test_common/harness/genericThread.cpp
../../test_common/harness/typeWrappers.cpp
../../test_common/harness/conversions.c
../../test_common/harness/mt19937.c
../../test_common/harness/msvc9.c
../../test_common/harness/parseParameters.cpp
)
set_source_files_properties(
COMPILE_FLAGS -msse2)
set_source_files_properties(
main.c
test_multiple_contexts.c
../../test_common/harness/errorHelpers.c
../../test_common/harness/threadTesting.c
../../test_common/harness/testHarness.c
../../test_common/harness/kernelHelpers.c
../../test_common/harness/conversions.c
../../test_common/harness/msvc9.c
../../test_common/harness/parseParameters.cpp
PROPERTIES LANGUAGE CXX)
include(../CMakeCommon.txt)

View File

@@ -0,0 +1,17 @@
project
: requirements
<toolset>gcc:<cflags>-xc++
<toolset>msvc:<cflags>"/TP"
;
exe test_multiple_device_context
: main.c
test_multiple_contexts.c
test_multiple_devices.cpp
;
install dist
: test_multiple_device_context
: <variant>debug:<location>$(DIST)/debug/tests/test_conformance/multiple_device_context
<variant>release:<location>$(DIST)/release/tests/test_conformance/multiple_device_context
;

View File

@@ -0,0 +1,46 @@
ifdef BUILD_WITH_ATF
ATF = -framework ATF
USE_ATF = -DUSE_ATF
endif
SRCS = main.c \
test_multiple_contexts.c \
test_multiple_devices.cpp \
../../test_common/harness/errorHelpers.c \
../../test_common/harness/threadTesting.c \
../../test_common/harness/testHarness.c \
../../test_common/harness/kernelHelpers.c \
../../test_common/harness/genericThread.cpp \
../../test_common/harness/mt19937.c \
../../test_common/harness/conversions.c \
../../test_common/harness/typeWrappers.cpp
DEFINES = DONT_TEST_GARBAGE_POINTERS
SOURCES = $(abspath $(SRCS))
LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries
LIBPATH += -L.
FRAMEWORK = $(SOURCES)
HEADERS =
TARGET = test_multiples
INCLUDE =
COMPILERFLAGS = -c -Wall -g -Wshorten-64-to-32
CC = c++
CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE)
CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE)
LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF}
OBJECTS := ${SOURCES:.c=.o}
OBJECTS := ${OBJECTS:.cpp=.o}
TARGETOBJECT =
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES)
clean:
rm -f $(TARGET) $(OBJECTS)
.DEFAULT:
@echo The target \"$@\" does not exist in Makefile.

View File

@@ -0,0 +1,62 @@
//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "../../test_common/harness/compat.h"
#include <stdio.h>
#include <string.h>
#include "procs.h"
#include "../../test_common/harness/testHarness.h"
#include "../../test_common/harness/mt19937.h"
#if !defined(_WIN32)
#include <unistd.h>
#endif
basefn basefn_list[] = {
test_multiple_contexts_same_device,
test_two_contexts_same_device,
test_three_contexts_same_device,
test_four_contexts_same_device,
test_two_devices,
test_max_devices,
test_hundred_queues
};
const char *basefn_names[] = {
"context_multiple_contexts_same_device",
"context_two_contexts_same_device",
"context_three_contexts_same_device",
"context_four_contexts_same_device",
"two_devices",
"max_devices",
"hundred_queues",
};
ct_assert((sizeof(basefn_names) / sizeof(basefn_names[0])) == (sizeof(basefn_list) / sizeof(basefn_list[0])));
int num_fns = sizeof(basefn_names) / sizeof(char *);
int main(int argc, const char *argv[])
{
return runTestHarness( argc, argv, num_fns, basefn_list, basefn_names, false, true, 0 );
}

View File

@@ -0,0 +1,31 @@
//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "../../test_common/harness/errorHelpers.h"
#include "../../test_common/harness/kernelHelpers.h"
#include "../../test_common/harness/typeWrappers.h"
#include "../../test_common/harness/mt19937.h"
extern int test_multiple_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_two_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_three_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_four_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_two_devices(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_max_devices(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
extern int test_hundred_queues(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements);

View File

@@ -0,0 +1,31 @@
//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef _testBase_h
#define _testBase_h
#include "../../test_common/harness/compat.h"
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "procs.h"
#endif // _testBase_h

View File

@@ -0,0 +1,529 @@
//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "testBase.h"
#include "../../test_common/harness/testHarness.h"
const char *context_test_kernels[] = {
"__kernel void sample_test_1(__global int *src, __global int *dst)\n"
"{\n"
" int tid = get_global_id(0);\n"
" dst[tid] = src[tid];\n"
"\n"
"}\n"
"__kernel void sample_test_2(__global int *src, __global int *dst)\n"
"{\n"
" int tid = get_global_id(0);\n"
" dst[tid] = src[tid] * 2;\n"
"\n"
"}\n"
"__kernel void sample_test_3(__global int *src, __global int *dst)\n"
"{\n"
" int tid = get_global_id(0);\n"
" dst[tid] = src[tid] / 2;\n"
"\n"
"}\n"
"__kernel void sample_test_4(__global int *src, __global int *dst)\n"
"{\n"
" int tid = get_global_id(0);\n"
" dst[tid] = src[tid] /3;\n"
"\n"
"}\n"
};
int sampleAction1( int source ) { return source; }
int sampleAction2( int source ) { return source * 2; }
int sampleAction3( int source ) { return source / 2; }
int sampleAction4( int source ) { return source / 3; }
typedef int (*sampleActionFn)( int source );
sampleActionFn sampleActions[4] = { sampleAction1, sampleAction2, sampleAction3, sampleAction4 };
#define BUFFER_COUNT 2
#define TEST_SIZE 512
typedef struct TestItem
{
struct TestItem *next;
cl_context c;
cl_command_queue q;
cl_program p;
cl_kernel k[4];
cl_mem m[BUFFER_COUNT];
MTdata d;
}TestItem;
static void DestroyTestItem( TestItem *item );
// Attempt to create a context and associated objects
TestItem *CreateTestItem( cl_device_id deviceID, cl_int *err )
{
cl_int error = 0;
size_t i;
// Allocate the TestItem struct
TestItem *item = (TestItem *) malloc( sizeof(TestItem ) );
if( NULL == item )
{
if( err )
{
log_error( "FAILURE: Failed to allocate TestItem -- out of host memory!\n" );
*err = CL_OUT_OF_HOST_MEMORY;
}
return NULL;
}
//zero so we know which fields we have initialized
memset( item, 0, sizeof( *item ) );
item->d = init_genrand( gRandomSeed );
if( NULL == item->d )
{
if( err )
{
log_error( "FAILURE: Failed to allocate mtdata om CreateTestItem -- out of host memory!\n" );
*err = CL_OUT_OF_HOST_MEMORY;
}
DestroyTestItem( item );
return NULL;
}
// Create a context
item->c = clCreateContext(NULL, 1, &deviceID, notify_callback, NULL, &error );
if( item->c == NULL || error != CL_SUCCESS)
{
if (err) {
log_error( "FAILURE: clCreateContext failed in CreateTestItem: %d\n", error);
*err = error;
}
DestroyTestItem( item );
return NULL;
}
// Create a queue
item->q = clCreateCommandQueueWithProperties( item->c, deviceID, 0, &error);
if( item->q == NULL || error != CL_SUCCESS)
{
if (err) {
log_error( "FAILURE: clCreateCommandQueue failed in CreateTestItem: %d\n", error );
*err = error;
}
DestroyTestItem( item );
return NULL;
}
// Create a program
error = create_single_kernel_helper_create_program(item->c, &item->p, 1, context_test_kernels);
if( NULL == item->p || CL_SUCCESS != error )
{
if( err )
{
log_error( "FAILURE: clCreateProgram failed in CreateTestItem: %d\n", error );
*err = error;
}
DestroyTestItem( item );
return NULL;
}
error = clBuildProgram( item->p, 1, &deviceID, "", NULL, NULL );
if( error )
{
if( err )
{
log_error( "FAILURE: clBuildProgram failed in CreateTestItem: %d\n", error );
*err = error;
}
DestroyTestItem( item );
return NULL;
}
// create some kernels
for( i = 0; i < sizeof( item->k ) / sizeof( item->k[0] ); i++ )
{
static const char *kernelNames[] = { "sample_test_1", "sample_test_2", "sample_test_3", "sample_test_4" };
item->k[i] = clCreateKernel( item->p, kernelNames[i], &error );
if( NULL == item->k[i] || CL_SUCCESS != error )
{
if( err )
{
log_error( "FAILURE: clCreateKernel( \"%s\" ) failed in CreateTestItem: %d\n", kernelNames[i], error );
*err = error;
}
DestroyTestItem( item );
return NULL;
}
}
// create some mem objects
for( i = 0; i < BUFFER_COUNT; i++ )
{
item->m[i] = clCreateBuffer( item->c, CL_MEM_READ_WRITE, TEST_SIZE * sizeof(cl_int), NULL, &error );
if( NULL == item->m[i] || CL_SUCCESS != error )
{
if( err )
{
log_error( "FAILURE: clCreateBuffer( %ld bytes ) failed in CreateTestItem: %d\n", TEST_SIZE * sizeof(cl_int), error );
*err = error;
}
DestroyTestItem( item );
return NULL;
}
}
return item;
}
// Destroy a context and associate objects
static void DestroyTestItem( TestItem *item )
{
size_t i;
if( NULL == item )
return;
if( item->d )
free_mtdata( item->d );
if( item->c)
clReleaseContext( item->c );
if( item->q)
clReleaseCommandQueue( item->q );
if( item->p)
clReleaseProgram( item->p );
for( i = 0; i < sizeof( item->k ) / sizeof( item->k[0] ); i++ )
{
if( item->k[i])
clReleaseKernel( item->k[i] );
}
for( i = 0; i < BUFFER_COUNT; i++ )
{
if( item->m[i])
clReleaseMemObject( item->m[i] );
}
free(item );
}
cl_int UseTestItem( const TestItem *item, cl_int *err )
{
size_t i, j;
cl_int error = CL_SUCCESS;
// Fill buffer 0 with random numbers
cl_int *mapped = (cl_int*) clEnqueueMapBuffer( item->q, item->m[0], CL_TRUE, CL_MAP_WRITE, 0, TEST_SIZE * sizeof( cl_int ), 0, NULL, NULL, &error );
if( NULL == mapped || CL_SUCCESS != error )
{
if( err )
{
log_error( "FAILURE: Failed to map buffer 0 for writing: %d\n", error );
*err = error;
}
return error;
}
for( j = 0; j < TEST_SIZE; j++ )
mapped[j] = genrand_int32(item->d);
error = clEnqueueUnmapMemObject( item->q, item->m[0], mapped, 0, NULL, NULL );
if( CL_SUCCESS != error )
{
if( err )
{
log_error( "FAILURE: failure to unmap buffer 0 for writing: %d\n", error );
*err = error;
}
return error;
}
// try each kernel in turn.
for( j = 0; j < sizeof(item->k) / sizeof( item->k[0] ); j++ )
{
// Fill buffer 1 with 0xdeaddead
mapped = (cl_int*) clEnqueueMapBuffer( item->q, item->m[1], CL_TRUE, CL_MAP_WRITE, 0, TEST_SIZE * sizeof( cl_int ), 0, NULL, NULL, &error );
if( NULL == mapped || CL_SUCCESS != error )
{
if( err )
{
log_error( "Failed to map buffer 1 for writing: %d\n", error );
*err = error;
}
return error;
}
for( i = 0; i < TEST_SIZE; i++ )
mapped[i] = 0xdeaddead;
error = clEnqueueUnmapMemObject( item->q, item->m[1], mapped, 0, NULL, NULL );
if( CL_SUCCESS != error )
{
if( err )
{
log_error( "Failed to unmap buffer 1 for writing: %d\n", error );
*err = error;
}
return error;
}
// Run the kernel
error = clSetKernelArg( item->k[j], 0, sizeof( cl_mem), &item->m[0] );
if( error )
{
if( err )
{
log_error( "FAILURE to set arg 0 for kernel # %ld : %d\n", j, error );
*err = error;
}
return error;
}
error = clSetKernelArg( item->k[j], 1, sizeof( cl_mem), &item->m[1] );
if( error )
{
if( err )
{
log_error( "FAILURE: Unable to set arg 1 for kernel # %ld : %d\n", j, error );
*err = error;
}
return error;
}
size_t work_size = TEST_SIZE;
size_t global_offset = 0;
error = clEnqueueNDRangeKernel( item->q, item->k[j], 1, &global_offset, &work_size, NULL, 0, NULL, NULL );
if( CL_SUCCESS != error )
{
if( err )
{
log_error( "FAILURE: Unable to enqueue kernel %ld: %d\n", j, error );
*err = error;
}
return error;
}
// Get the results back
mapped = (cl_int*) clEnqueueMapBuffer( item->q, item->m[1], CL_TRUE, CL_MAP_READ, 0, TEST_SIZE * sizeof( cl_int ), 0, NULL, NULL, &error );
if( NULL == mapped || CL_SUCCESS != error )
{
if( err )
{
log_error( "Failed to map buffer 1 for reading: %d\n", error );
*err = error;
}
return error;
}
// Get our input data so we can check against it
cl_int *inputData = (cl_int*) clEnqueueMapBuffer( item->q, item->m[0], CL_TRUE, CL_MAP_READ, 0, TEST_SIZE * sizeof( cl_int ), 0, NULL, NULL, &error );
if( NULL == mapped || CL_SUCCESS != error )
{
if( err )
{
log_error( "Failed to map buffer 0 for reading: %d\n", error );
*err = error;
}
return error;
}
//Verify the results
for( i = 0; i < TEST_SIZE; i++ )
{
int expected = sampleActions[j]( inputData[i] );
int result = mapped[i];
if( expected != result )
{
log_error( "FAILURE: Sample data at position %ld does not match expected result: *0x%8.8x vs. 0x%8.8x\n", i, expected, result );
if( err )
*err = -1;
return -1;
}
}
//Clean up
error = clEnqueueUnmapMemObject( item->q, item->m[0], inputData, 0, NULL, NULL );
if( CL_SUCCESS != error )
{
if( err )
{
log_error( "Failed to unmap buffer 0 for reading: %d\n", error );
*err = error;
}
return error;
}
error = clEnqueueUnmapMemObject( item->q, item->m[1], mapped, 0, NULL, NULL );
if( CL_SUCCESS != error )
{
if( err )
{
log_error( "Failed to unmap buffer 1 for reading: %d\n", error );
*err = error;
}
return error;
}
}
// Make sure that the last set of unmap calls get run
error = clFinish( item->q );
if( CL_SUCCESS != error )
{
if( err )
{
log_error( "Failed to clFinish: %d\n", error );
*err = error;
}
return error;
}
return CL_SUCCESS;
}
int test_multiple_contexts_same_device(cl_device_id deviceID, size_t maxCount, size_t minCount )
{
size_t i, j;
cl_int err = CL_SUCCESS;
//Figure out how many of these we can make before the first failure
TestItem *list = NULL;
for( i = 0; i < maxCount; i++ )
{
// create a context and accompanying objects
TestItem *current = CreateTestItem( deviceID, NULL /*no error reporting*/ );
if( NULL == current )
break;
// Attempt to use it
cl_int failed = UseTestItem( current, NULL );
if( failed )
{
DestroyTestItem( current );
break;
}
// Add the successful test item to the list
current->next = list;
list = current;
}
// Check to make sure we made the minimum amount
if( i < minCount )
{
log_error( "FAILURE: only could make %ld of %ld contexts!\n", i, minCount );
err = -1;
goto exit;
}
// Report how many contexts we made
if( i == maxCount )
log_info( "Successfully created all %lu contexts.\n", i );
else
log_info( "Successfully created %lu contexts out of %lu\n", i, maxCount );
// Set the count to be the number we succesfully made
maxCount = i;
// Make sure we can do it again a few times
log_info( "Tring to do it 5 more times" );
fflush( stdout);
for( j = 0; j < 5; j++ )
{
//free all the contexts we already made
while( list )
{
TestItem *current = list;
list = list->next;
current->next = NULL;
DestroyTestItem( current );
}
// Attempt to make them again
for( i = 0; i < maxCount; i++ )
{
// create a context and accompanying objects
TestItem *current = CreateTestItem( deviceID, &err );
if( err )
{
log_error( "\nTest Failed with error at CreateTestItem: %d\n", err );
goto exit;
}
// Attempt to use it
cl_int failed = UseTestItem( current, &err );
if( failed || err )
{
DestroyTestItem( current );
log_error( "\nTest Failed with error at UseTestItem: %d\n", err );
goto exit;
}
// Add the successful test item to the list
current->next = list;
list = current;
}
log_info( "." );
fflush( stdout );
}
log_info( "Done.\n" );
exit:
//free all the contexts we already made
while( list )
{
TestItem *current = list;
list = list->next;
current->next = NULL;
DestroyTestItem( current );
}
return err;
}
// This test tests to make sure that your implementation isn't super leaky. We make a bunch of contexts (up to some
// sane limit, currently 200), attempting to use each along the way. We keep track of how many we could make before
// a failure occurred. We then free everything and attempt to go do it again a few times. If you are able to make
// that many contexts 5 times over, then you pass.
int test_multiple_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_multiple_contexts_same_device( deviceID, 200, 1 );
}
int test_two_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_multiple_contexts_same_device( deviceID, 2, 2 );
}
int test_three_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_multiple_contexts_same_device( deviceID, 3, 3 );
}
int test_four_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
return test_multiple_contexts_same_device( deviceID, 4, 4 );
}

View File

@@ -0,0 +1,236 @@
//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "testBase.h"
#include "../../test_common/harness/typeWrappers.h"
#include "../../test_common/harness/testHarness.h"
#include "../../test_common/harness/conversions.h"
const char *test_kernels[] = {
"__kernel void kernelA(__global int *dst)\n"
"{\n"
"\n"
" dst[get_global_id(0)]*=3;\n"
"\n"
"}\n"
"__kernel void kernelB(__global int *dst)\n"
"{\n"
"\n"
" dst[get_global_id(0)]++;\n"
"\n"
"}\n"
};
#define TEST_SIZE 512
#define MAX_DEVICES 8
#define MAX_QUEUES 1000
int test_device_set(size_t deviceCount, size_t queueCount, cl_device_id *devices, int num_elements)
{
int error;
clContextWrapper context;
clProgramWrapper program;
clKernelWrapper kernels[2];
clMemWrapper stream;
clCommandQueueWrapper queues[MAX_QUEUES];
size_t threads[1], localThreads[1];
int data[TEST_SIZE];
int outputData[TEST_SIZE];
int expectedResults[TEST_SIZE];
int expectedResultsOneDevice[MAX_DEVICES][TEST_SIZE];
size_t i;
memset(queues, 0, sizeof(queues));
RandomSeed seed( gRandomSeed );
if (deviceCount > MAX_DEVICES) {
log_error("Number of devices in set (%ld) is greater than the number for which the test was written (%d).", deviceCount, MAX_DEVICES);
return -1;
}
if (queueCount > MAX_QUEUES) {
log_error("Number of queues (%ld) is greater than the number for which the test was written (%d).", queueCount, MAX_QUEUES);
return -1;
}
log_info("Testing with %ld queues on %ld devices, %ld kernel executions.\n", queueCount, deviceCount, queueCount*num_elements/TEST_SIZE);
for (i=0; i<deviceCount; i++) {
char deviceName[4096] = "";
error = clGetDeviceInfo(devices[i], CL_DEVICE_NAME, sizeof(deviceName), deviceName, NULL);
test_error(error, "clGetDeviceInfo CL_DEVICE_NAME failed");
log_info("Device %ld is \"%s\".\n", i, deviceName);
}
/* Create a context */
context = clCreateContext( NULL, (cl_uint)deviceCount, devices, notify_callback, NULL, &error );
test_error( error, "Unable to create testing context" );
/* Create our kernels (they all have the same arguments so we don't need multiple ones for each device) */
if( create_single_kernel_helper( context, &program, &kernels[0], 1, test_kernels, "kernelA" ) != 0 )
{
return -1;
}
kernels[1] = clCreateKernel(program, "kernelB", &error);
test_error(error, "clCreateKernel failed");
/* Now create I/O streams */
for( i = 0; i < TEST_SIZE; i++ )
data[i] = genrand_int32(seed);
stream = clCreateBuffer(context, (cl_mem_flags)(CL_MEM_COPY_HOST_PTR), sizeof(cl_int) * TEST_SIZE, data, &error);
test_error( error, "Unable to create test array" );
// Update the expected results
for( i = 0; i < TEST_SIZE; i++ ) {
expectedResults[i] = data[i];
for (size_t j=0; j<deviceCount; j++)
expectedResultsOneDevice[j][i] = data[i];
}
// Set the arguments
error = clSetKernelArg( kernels[0], 0, sizeof( stream ), &stream);
test_error( error, "Unable to set kernel arguments" );
error = clSetKernelArg( kernels[1], 0, sizeof( stream ), &stream);
test_error( error, "Unable to set kernel arguments" );
/* Run the test */
threads[0] = (size_t)TEST_SIZE;
error = get_max_common_work_group_size( context, kernels[0], threads[0], &localThreads[ 0 ] );
test_error( error, "Unable to calc work group size" );
/* Create work queues */
for( i = 0; i < queueCount; i++ )
{
queues[i] = clCreateCommandQueueWithProperties( context, devices[ i % deviceCount ], 0, &error );
if (error != CL_SUCCESS || queues[i] == NULL) {
log_info("Could not create queue[%d].\n", (int)i);
queueCount = i;
break;
}
}
log_info("Testing with %d queues.\n", (int)queueCount);
/* Enqueue executions */
for( int z = 0; z<num_elements/TEST_SIZE; z++) {
for( i = 0; i < queueCount; i++ )
{
// Randomly choose a kernel to execute.
int kernel_selection = (int)get_random_float(0, 2, seed);
error = clEnqueueNDRangeKernel( queues[ i ], kernels[ kernel_selection ], 1, NULL, threads, localThreads, 0, NULL, NULL );
test_error( error, "Kernel execution failed" );
// Update the expected results
for( int j = 0; j < TEST_SIZE; j++ ) {
expectedResults[j] = (kernel_selection) ? expectedResults[j]+1 : expectedResults[j]*3;
expectedResultsOneDevice[i % deviceCount][j] = (kernel_selection) ? expectedResultsOneDevice[i % deviceCount][j]+1 : expectedResultsOneDevice[i % deviceCount][j]*3;
}
// Force the queue to finish so the next one will be in sync
error = clFinish(queues[i]);
test_error( error, "clFinish failed");
}
}
/* Read results */
int errors = 0;
for (int q = 0; q<(int)queueCount; q++) {
error = clEnqueueReadBuffer( queues[ 0 ], stream, CL_TRUE, 0, sizeof(cl_int)*TEST_SIZE, (char *)outputData, 0, NULL, NULL );
test_error( error, "Unable to get result data set" );
int errorsThisTime = 0;
/* Verify all of the data now */
for( i = 0; i < TEST_SIZE; i++ )
{
if( expectedResults[ i ] != outputData[ i ] )
{
log_error( "ERROR: Sample data did not verify for queue %d on device %ld (sample %d, expected %d, got %d)\n",
q, q % deviceCount, (int)i, expectedResults[ i ], outputData[ i ] );
for (size_t j=0; j<deviceCount; j++) {
if (expectedResultsOneDevice[j][i] == outputData[i])
log_info("Sample consistent with only device %ld having modified the data.\n", j);
}
errorsThisTime++;
break;
}
}
if (errorsThisTime)
errors++;
}
/* All done now! */
if (errors)
return -1;
return 0;
}
int test_two_devices(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
cl_platform_id platform;
cl_device_id devices[2];
int err;
cl_uint numDevices;
err = clGetPlatformIDs(1, &platform, NULL);
test_error( err, "Unable to get platform" );
/* Get some devices */
err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 2, devices, &numDevices );
test_error( err, "Unable to get 2 devices" );
if( numDevices < 2 )
{
log_info( "WARNING: two device test unable to get two devices via CL_DEVICE_TYPE_ALL (got %d devices). Skipping test...\n", (int)numDevices );
return 0;
}
else if (numDevices > 2)
{
log_info("Note: got %d devices, using just the first two.\n", (int)numDevices);
}
/* Run test */
return test_device_set( 2, 2, devices, num_elements );
}
int test_max_devices(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
{
cl_platform_id platform;
cl_device_id devices[MAX_DEVICES];
cl_uint deviceCount;
int err;
err = clGetPlatformIDs(1, &platform, NULL);
test_error( err, "Unable to get platform" );
/* Get some devices */
err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, MAX_DEVICES, devices, &deviceCount );
test_error( err, "Unable to get multiple devices" );
log_info("Testing with %d devices.", deviceCount);
/* Run test */
return test_device_set( deviceCount, deviceCount, devices, num_elements );
}
int test_hundred_queues(cl_device_id device, cl_context contextIgnore, cl_command_queue queueIgnore, int num_elements)
{
return test_device_set( 1, 100, &device, num_elements );
}