// // 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 #include #include "procs.h" #include "harness/errorHelpers.h" #include "harness/testHarness.h" #define MAX_SUB_DEVICES 16 // Limit the sub-devices to ensure no out of resource errors. #define BUFFER_SIZE 1024 // Kernel source code static const char *buffer_migrate_kernel_code = "__kernel void test_buffer_migrate(__global uint *dst, __global uint *src1, __global uint *src2, uint x)\n" "{\n" " int tid = get_global_id(0);\n" " dst[tid] = src1[tid] ^ src2[tid] ^ x;\n" "}\n"; enum migrations { MIGRATE_PREFERRED, // migrate to the preferred sub-device MIGRATE_NON_PREFERRED, // migrate to a randomly chosen non-preferred sub-device MIGRATE_RANDOM, // migrate to a randomly chosen sub-device with randomly chosen flags NUMBER_OF_MIGRATIONS }; static cl_mem init_buffer(cl_command_queue cmd_q, cl_mem buffer, cl_uint *data) { cl_int err; if (buffer) { if ((err = clEnqueueWriteBuffer(cmd_q, buffer, CL_TRUE, 0, sizeof(cl_uint)*BUFFER_SIZE, data, 0, NULL, NULL)) != CL_SUCCESS) { print_error(err, "Failed on enqueue write of buffer data."); } } return buffer; } static cl_int migrateMemObject(enum migrations migrate, cl_command_queue *queues, cl_mem *mem_objects, cl_uint num_devices, cl_mem_migration_flags *flags, MTdata d) { cl_uint i, j; cl_int err = CL_SUCCESS; for (i=0; i 1)) j = (j+1) % num_devices; break; case MIGRATE_RANDOM: // Choose a random set of flags flags[i] = (cl_mem_migration_flags)(genrand_int32(d) & (CL_MIGRATE_MEM_OBJECT_HOST | CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED));; break; default: log_error("Unhandled migration type: %d\n", migrate); return -1; } if ((err = clEnqueueMigrateMemObjects(queues[j], 1, (const cl_mem *)(&mem_objects[i]), flags[i], 0, NULL, NULL)) != CL_SUCCESS) { print_error(err, "Failed migrating memory object."); } } return err; } static cl_int restoreBuffer(cl_command_queue *queues, cl_mem *buffers, cl_uint num_devices, cl_mem_migration_flags *flags, cl_uint *buffer) { cl_uint i, j; cl_int err; // If the buffer was previously migrated with undefined content, reload the content. for (i=0; i 1) { // Create each of the sub-devices and a corresponding context. if ((err = clCreateSubDevices(deviceID, (const cl_device_partition_property *)property, num_devices, devices, &num_devices)) != CL_SUCCESS) { print_error(err, "Failed creating sub devices."); failed = 1; goto cleanup; } // Create a context containing all the sub-devices ctx = clCreateContext(NULL, num_devices, devices, notify_callback, NULL, &err); if (ctx == NULL) { print_error(err, "Failed creating context containing the sub-devices."); failed = 1; goto cleanup; } // Create a command queue for each sub-device for (i=0; i 1) { // Command queue cleanup if (queues[i]) { if ((err = clReleaseCommandQueue(queues[i])) != CL_SUCCESS) { print_error(err, "Failed releasing command queue."); failed = 1; } } // Sub-device cleanup if (devices[i]) { if ((err = clReleaseDevice(devices[i])) != CL_SUCCESS) { print_error(err, "Failed releasing sub device."); failed = 1; } } devices[i] = 0; } } // Context, program, and kernel cleanup if (program) { if ((err = clReleaseProgram(program)) != CL_SUCCESS) { print_error(err, "Failed releasing program."); failed = 1; } program = NULL; } if (kernel) { if ((err = clReleaseKernel(kernel)) != CL_SUCCESS) { print_error(err, "Failed releasing kernel."); failed = 1; } kernel = NULL; } if (ctx && (ctx != context)) { if ((err = clReleaseContext(ctx)) != CL_SUCCESS) { print_error(err, "Failed releasing context."); failed = 1; } } ctx = NULL; if (failed) goto cleanup_allocations; } while (domains); cleanup_allocations: if (devices) free(devices); if (queues) free(queues); if (flagsA) free(flagsA); if (flagsB) free(flagsB); if (flagsC) free(flagsC); if (bufferA) free(bufferA); if (bufferB) free(bufferB); if (bufferC) free(bufferC); return ((failed) ? -1 : 0); }