/* * Copyright (c) Advanced Micro Devices, Inc., or its affiliates. * * SPDX-License-Identifier: MIT */ #include "OCLPerfSdiP2PCopy.h" #include #include "Timer.h" #ifdef WIN_OS #define SNPRINTF sprintf_s #else #define SNPRINTF snprintf #endif #define NUM_SIZES 5 // 64KB, 256KB, 1 MB, 4MB, 16 MB static const unsigned int Sizes[NUM_SIZES] = {65536, 262144, 1048576, 4194304, 16777216}; OCLPerfSdiP2PCopy::OCLPerfSdiP2PCopy() { // If there are two different gpus in the system, // we have to test each of them _numSubTests = 2 * NUM_SIZES; } OCLPerfSdiP2PCopy::~OCLPerfSdiP2PCopy() {} void OCLPerfSdiP2PCopy::open(unsigned int test, char* units, double& conversion, unsigned int deviceId) { cl_uint numPlatforms = 0; cl_platform_id platform = NULL; cl_uint num_devices = 0; _crcword = 0; conversion = 1.0f; _openTest = test % NUM_SIZES; bufSize_ = Sizes[_openTest]; error_ = 0; srcBuff_ = 0; inputArr_ = 0; outputArr_ = 0; extPhysicalBuff_ = 0; silentFailure = false; busAddressableBuff_ = 0; devices_[0] = devices_[1] = 0; contexts_[0] = contexts_[1] = 0; cmd_queues_[0] = cmd_queues_[1] = 0; error_ = _wrapper->clGetPlatformIDs(0, NULL, &numPlatforms); CHECK_RESULT(numPlatforms == 0, "clGetPlatformIDs failed"); error_ = _wrapper->clGetPlatformIDs(1, &platform, NULL); CHECK_RESULT(error_ != CL_SUCCESS, "clGetPlatformIDs failed"); error_ = _wrapper->clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, NULL, &num_devices); if (num_devices != 2) { printf( "\nSilent Failure: Two GPUs are required to run OCLPerfSdiP2PCopy " "test\n"); silentFailure = true; return; } error_ = _wrapper->clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, num_devices, devices_, 0); CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceIDs failed"); if (test >= NUM_SIZES) { cl_device_id temp = devices_[0]; devices_[0] = devices_[1]; devices_[1] = temp; } size_t param_size = 0; char* strExtensions = 0; error_ = _wrapper->clGetDeviceInfo(devices_[0], CL_DEVICE_EXTENSIONS, 0, 0, ¶m_size); CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceInfo failed"); strExtensions = (char*)malloc(param_size); error_ = _wrapper->clGetDeviceInfo(devices_[0], CL_DEVICE_EXTENSIONS, param_size, strExtensions, 0); CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceInfo failed"); if (strstr(strExtensions, "cl_amd_bus_addressable_memory") == 0) { printf( "\nSilent Failure: cl_amd_bus_addressable_memory extension is not " "enabled on GPU 0\n"); silentFailure = true; free(strExtensions); return; } free(strExtensions); error_ = _wrapper->clGetDeviceInfo(devices_[1], CL_DEVICE_EXTENSIONS, 0, 0, ¶m_size); CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceInfo failed"); strExtensions = (char*)malloc(param_size); error_ = _wrapper->clGetDeviceInfo(devices_[1], CL_DEVICE_EXTENSIONS, param_size, strExtensions, 0); CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceInfo failed"); if (strstr(strExtensions, "cl_amd_bus_addressable_memory") == 0) { printf( "\nSilent Failure: cl_amd_bus_addressable_memory extension is not " "enabled on GPU 1\n"); silentFailure = true; free(strExtensions); return; } free(strExtensions); deviceNames_ = " ["; param_size = 0; char* strDeviceName = 0; error_ = _wrapper->clGetDeviceInfo(devices_[1], CL_DEVICE_NAME, 0, 0, ¶m_size); CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceInfo failed"); strDeviceName = (char*)malloc(param_size); error_ = _wrapper->clGetDeviceInfo(devices_[1], CL_DEVICE_NAME, param_size, strDeviceName, 0); CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceInfo failed"); deviceNames_ = deviceNames_ + strDeviceName; free(strDeviceName); error_ = _wrapper->clGetDeviceInfo(devices_[0], CL_DEVICE_NAME, 0, 0, ¶m_size); CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceInfo failed"); strDeviceName = (char*)malloc(param_size); error_ = _wrapper->clGetDeviceInfo(devices_[0], CL_DEVICE_NAME, param_size, strDeviceName, 0); CHECK_RESULT(error_ != CL_SUCCESS, "clGetDeviceInfo failed"); deviceNames_ = deviceNames_ + "->"; deviceNames_ = deviceNames_ + strDeviceName; free(strDeviceName); deviceNames_ = deviceNames_ + "]"; cl_context_properties props[3] = {CL_CONTEXT_PLATFORM, (cl_context_properties)platform, 0}; contexts_[0] = _wrapper->clCreateContext(props, 1, &devices_[0], 0, 0, &error_); CHECK_RESULT(contexts_[0] == 0, "clCreateContext failed"); contexts_[1] = _wrapper->clCreateContext(props, 1, &devices_[1], 0, 0, &error_); CHECK_RESULT(contexts_[1] == 0, "clCreateContext failed"); cmd_queues_[0] = _wrapper->clCreateCommandQueue(contexts_[0], devices_[0], 0, NULL); CHECK_RESULT(cmd_queues_[0] == 0, "clCreateCommandQueue failed"); cmd_queues_[1] = _wrapper->clCreateCommandQueue(contexts_[1], devices_[1], 0, NULL); CHECK_RESULT(cmd_queues_[1] == 0, "clCreateCommandQueue failed"); busAddressableBuff_ = _wrapper->clCreateBuffer(contexts_[0], CL_MEM_BUS_ADDRESSABLE_AMD, bufSize_, 0, &error_); CHECK_RESULT((error_ != CL_SUCCESS), "clCreateBuffer failed"); error_ = _wrapper->clEnqueueMakeBuffersResidentAMD(cmd_queues_[0], 1, &busAddressableBuff_, true, &busAddr_, 0, 0, 0); CHECK_RESULT((error_ != CL_SUCCESS), "clEnqueueMakeBuffersResidentAMD failed"); extPhysicalBuff_ = _wrapper->clCreateBuffer(contexts_[1], CL_MEM_EXTERNAL_PHYSICAL_AMD, bufSize_, &busAddr_, &error_); CHECK_RESULT((error_ != CL_SUCCESS), "clCreateBuffer failed"); srcBuff_ = _wrapper->clCreateBuffer(contexts_[1], CL_MEM_READ_WRITE, bufSize_, 0, &error_); CHECK_RESULT(error_ != CL_SUCCESS, "clCreateBuffer failed"); inputArr_ = (cl_uint*)malloc(bufSize_); outputArr_ = (cl_uint*)malloc(bufSize_); for (unsigned int i = 0; i < (bufSize_ / sizeof(cl_uint)); ++i) { inputArr_[i] = i + 1; outputArr_[i] = 0; } error_ = _wrapper->clEnqueueWriteBuffer(cmd_queues_[1], srcBuff_, CL_TRUE, 0, bufSize_, inputArr_, 0, 0, NULL); CHECK_RESULT(error_ != CL_SUCCESS, "clEnqueueWriteBuffer failed"); } void OCLPerfSdiP2PCopy::run(void) { if (silentFailure) { return; } CPerfCounter timer; // Warm up error_ = _wrapper->clEnqueueCopyBuffer(cmd_queues_[1], srcBuff_, extPhysicalBuff_, 0, 0, bufSize_, 0, NULL, NULL); CHECK_RESULT(error_, "clEnqueueCopyBuffer failed"); error_ = _wrapper->clFinish(cmd_queues_[1]); CHECK_RESULT(error_, "clFinish failed"); timer.Reset(); timer.Start(); for (unsigned int i = 0; i < NUM_ITER; i++) { error_ = _wrapper->clEnqueueCopyBuffer(cmd_queues_[1], srcBuff_, extPhysicalBuff_, 0, 0, bufSize_, 0, NULL, NULL); CHECK_RESULT(error_, "clEnqueueCopyBuffer failed"); } error_ = _wrapper->clFinish(cmd_queues_[1]); CHECK_RESULT(error_, "clFinish failed"); timer.Stop(); double sec = timer.GetElapsedTime(); error_ = _wrapper->clEnqueueReadBuffer(cmd_queues_[0], busAddressableBuff_, CL_TRUE, 0, bufSize_, outputArr_, 0, 0, NULL); CHECK_RESULT(error_ != CL_SUCCESS, "clEnqueueWriteBuffer failed"); CHECK_RESULT((memcmp(inputArr_, outputArr_, bufSize_) != 0), "copy failed"); // Buffer copy bandwidth in GB/s double perf = ((double)bufSize_ * NUM_ITER * (double)(1e-09)) / sec; _perfInfo = (float)perf; char buf[256]; SNPRINTF(buf, sizeof(buf), " (%8d bytes) i:%4d (GB/s) %s", bufSize_, NUM_ITER, deviceNames_.c_str()); testDescString = buf; } unsigned int OCLPerfSdiP2PCopy::close(void) { if (srcBuff_) { error_ = _wrapper->clReleaseMemObject(srcBuff_); CHECK_RESULT_NO_RETURN(error_ != CL_SUCCESS, "clReleaseMemObject failed"); } if (extPhysicalBuff_) { error_ = _wrapper->clReleaseMemObject(extPhysicalBuff_); CHECK_RESULT_NO_RETURN(error_ != CL_SUCCESS, "clReleaseMemObject failed"); } if (busAddressableBuff_) { error_ = _wrapper->clReleaseMemObject(busAddressableBuff_); CHECK_RESULT_NO_RETURN(error_ != CL_SUCCESS, "clReleaseMemObject failed"); } if (cmd_queues_[0]) { error_ = _wrapper->clReleaseCommandQueue(cmd_queues_[0]); CHECK_RESULT_NO_RETURN(error_ != CL_SUCCESS, "clReleaseCommandQueue failed"); } if (cmd_queues_[1]) { error_ = _wrapper->clReleaseCommandQueue(cmd_queues_[1]); CHECK_RESULT_NO_RETURN(error_ != CL_SUCCESS, "clReleaseCommandQueue failed"); } if (contexts_[0]) { error_ = _wrapper->clReleaseContext(contexts_[0]); CHECK_RESULT_NO_RETURN(error_ != CL_SUCCESS, "clReleaseContext failed"); } if (contexts_[1]) { error_ = _wrapper->clReleaseContext(contexts_[1]); CHECK_RESULT_NO_RETURN(error_ != CL_SUCCESS, "clReleaseContext failed"); } if (inputArr_) { free(inputArr_); } if (outputArr_) { free(outputArr_); } return _crcword; }