diff --git a/opencl/source/api/api.cpp b/opencl/source/api/api.cpp index 0d44590299..c5c66fe777 100644 --- a/opencl/source/api/api.cpp +++ b/opencl/source/api/api.cpp @@ -326,41 +326,50 @@ cl_int CL_API_CALL clCreateSubDevices(cl_device_id inDevice, cl_uint numDevices, cl_device_id *outDevices, cl_uint *numDevicesRet) { + TRACING_ENTER(ClCreateSubDevices, &inDevice, &properties, &numDevices, &outDevices, &numDevicesRet); + cl_int retVal = CL_INVALID_DEVICE; + API_ENTER(&retVal); + do { + ClDevice *pInDevice = castToObject(inDevice); + if (pInDevice == nullptr) { + break; + } + auto subDevicesCount = pInDevice->getNumSubDevices(); + if (subDevicesCount <= 1) { + retVal = CL_DEVICE_PARTITION_FAILED; + break; + } + if ((properties == nullptr) || + (properties[0] != CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN) || + ((properties[1] != CL_DEVICE_AFFINITY_DOMAIN_NUMA) && (properties[1] != CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE)) || + (properties[2] != 0)) { + retVal = CL_INVALID_VALUE; + break; + } - ClDevice *pInDevice = castToObject(inDevice); - if (pInDevice == nullptr) { - return CL_INVALID_DEVICE; - } - auto subDevicesCount = pInDevice->getNumSubDevices(); - if (subDevicesCount <= 1) { - return CL_DEVICE_PARTITION_FAILED; - } - if ((properties == nullptr) || - (properties[0] != CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN) || - ((properties[1] != CL_DEVICE_AFFINITY_DOMAIN_NUMA) && (properties[1] != CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE)) || - (properties[2] != 0)) { - return CL_INVALID_VALUE; - } + if (numDevicesRet != nullptr) { + *numDevicesRet = subDevicesCount; + } - if (numDevicesRet != nullptr) { - *numDevicesRet = subDevicesCount; - } + if (outDevices == nullptr) { + retVal = CL_SUCCESS; + break; + } - if (outDevices == nullptr) { - return CL_SUCCESS; - } + if (numDevices < subDevicesCount) { + retVal = CL_INVALID_VALUE; + break; + } - if (numDevices < subDevicesCount) { - return CL_INVALID_VALUE; - } - - for (uint32_t i = 0; i < subDevicesCount; i++) { - auto pClDevice = pInDevice->getSubDevice(i); - pClDevice->retainApi(); - outDevices[i] = pClDevice; - } - - return CL_SUCCESS; + for (uint32_t i = 0; i < subDevicesCount; i++) { + auto pClDevice = pInDevice->getSubDevice(i); + pClDevice->retainApi(); + outDevices[i] = pClDevice; + } + retVal = CL_SUCCESS; + } while (false); + TRACING_EXIT(ClCreateSubDevices, &retVal); + return retVal; } cl_int CL_API_CALL clRetainDevice(cl_device_id device) { diff --git a/opencl/source/tracing/tracing_notify.h b/opencl/source/tracing/tracing_notify.h index 5c43de76a7..8df33d875e 100644 --- a/opencl/source/tracing/tracing_notify.h +++ b/opencl/source/tracing/tracing_notify.h @@ -1001,6 +1001,75 @@ class ClCreateKernelsInProgramTracer { tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED; }; +class ClCreateSubDevicesTracer { + public: + ClCreateSubDevicesTracer() {} + + void enter(cl_device_id *inDevice, + const cl_device_partition_property **properties, + cl_uint *numDevices, + cl_device_id **outDevices, + cl_uint **numDevicesRet) { + DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_NOTHING_CALLED); + + params.inDevice = inDevice; + params.properties = properties; + params.numDevices = numDevices; + params.outDevices = outDevices; + params.numDevicesRet = numDevicesRet; + + data.site = CL_CALLBACK_SITE_ENTER; + data.correlationId = tracingCorrelationId.fetch_add(1, std::memory_order_acq_rel); + data.functionName = "clCreateSubDevices"; + data.functionParams = static_cast(¶ms); + data.functionReturnValue = nullptr; + + size_t i = 0; + DEBUG_BREAK_IF(tracingHandle[0] == nullptr); + while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) { + TracingHandle *handle = tracingHandle[i]; + DEBUG_BREAK_IF(handle == nullptr); + if (handle->getTracingPoint(CL_FUNCTION_clCreateSubDevices)) { + data.correlationData = correlationData + i; + handle->call(CL_FUNCTION_clCreateSubDevices, &data); + } + ++i; + } + + state = TRACING_NOTIFY_STATE_ENTER_CALLED; + } + + void exit(cl_int *retVal) { + DEBUG_BREAK_IF(state != TRACING_NOTIFY_STATE_ENTER_CALLED); + data.site = CL_CALLBACK_SITE_EXIT; + data.functionReturnValue = retVal; + + size_t i = 0; + DEBUG_BREAK_IF(tracingHandle[0] == nullptr); + while (i < TRACING_MAX_HANDLE_COUNT && tracingHandle[i] != nullptr) { + TracingHandle *handle = tracingHandle[i]; + DEBUG_BREAK_IF(handle == nullptr); + if (handle->getTracingPoint(CL_FUNCTION_clCreateSubDevices)) { + data.correlationData = correlationData + i; + handle->call(CL_FUNCTION_clCreateSubDevices, &data); + } + ++i; + } + + state = TRACING_NOTIFY_STATE_EXIT_CALLED; + } + + ~ClCreateSubDevicesTracer() { + DEBUG_BREAK_IF(state == TRACING_NOTIFY_STATE_ENTER_CALLED); + } + + private: + cl_params_clCreateSubDevices params{}; + cl_callback_data data{}; + uint64_t correlationData[TRACING_MAX_HANDLE_COUNT]; + tracing_notify_state_t state = TRACING_NOTIFY_STATE_NOTHING_CALLED; +}; + class ClCreatePipeTracer { public: ClCreatePipeTracer() {} diff --git a/opencl/test/unit_test/api/cl_intel_tracing_tests.inl b/opencl/test/unit_test/api/cl_intel_tracing_tests.inl index fceaac197b..3fbff63ed7 100644 --- a/opencl/test/unit_test/api/cl_intel_tracing_tests.inl +++ b/opencl/test/unit_test/api/cl_intel_tracing_tests.inl @@ -349,6 +349,10 @@ struct IntelAllTracingTest : public IntelTracingTest { functionId = CL_FUNCTION_clCreateSubBuffer; clCreateSubBuffer(0, 0, 0, 0, 0); + ++count; + functionId = CL_FUNCTION_clCreateSubDevices; + clCreateSubDevices(0, 0, 0, 0, 0); + ++count; functionId = CL_FUNCTION_clCreateUserEvent; clCreateUserEvent(0, 0); @@ -1126,4 +1130,79 @@ TEST_F(IntelClCloneKernelTracingTest, givenCloneKernelCallTracingWhenInvokingCal clReleaseKernel(clonedKernel); } +struct IntelClCreateSubDevicesTracingTest : public IntelTracingTest { + public: + void SetUp() override { + IntelTracingTest::setUp(); + + DebugManager.flags.CreateMultipleSubDevices.set(deviceCount); + device = std::make_unique(MockDevice::createWithNewExecutionEnvironment(defaultHwInfo.get())); + + status = clCreateTracingHandleINTEL(testedClDevice, callback, this, &handle); + ASSERT_NE(nullptr, handle); + ASSERT_EQ(CL_SUCCESS, status); + + status = clSetTracingPointINTEL(handle, CL_FUNCTION_clCreateSubDevices, CL_TRUE); + ASSERT_EQ(CL_SUCCESS, status); + + status = clEnableTracingINTEL(handle); + ASSERT_EQ(CL_SUCCESS, status); + } + void TearDown() override { + status = clDisableTracingINTEL(handle); + ASSERT_EQ(CL_SUCCESS, status); + + status = clDestroyTracingHandleINTEL(handle); + ASSERT_EQ(CL_SUCCESS, status); + IntelTracingTest::tearDown(); + } + + void call() { + auto retVal = clCreateSubDevices(device.get(), properties, deviceCount, outDevices, numDevicesRet); + ASSERT_EQ(CL_SUCCESS, retVal); + } + + void vcallback(cl_function_id fid, cl_callback_data *callbackData, void *userData) override { + ASSERT_EQ(CL_FUNCTION_clCreateSubDevices, fid); + if (callbackData->site == CL_CALLBACK_SITE_ENTER) { + ++enterCount; + } else if (callbackData->site == CL_CALLBACK_SITE_EXIT) { + auto funcParams = reinterpret_cast(callbackData->functionParams); // check at tracing exit, once api call has been executed + EXPECT_EQ(static_cast(device.get()), *(funcParams->inDevice)); + EXPECT_EQ(2u, *(funcParams->numDevices)); + EXPECT_EQ(numDevicesRet[0], *(funcParams->numDevicesRet[0])); + + auto outDevicesCallback = *(funcParams->outDevices); + EXPECT_EQ(static_cast(device->getSubDevice(0)), outDevicesCallback[0]); + EXPECT_EQ(static_cast(device->getSubDevice(1)), outDevicesCallback[1]); + + auto propertiesCallback = *(funcParams->properties); + EXPECT_EQ(CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN, propertiesCallback[0]); + EXPECT_EQ(CL_DEVICE_AFFINITY_DOMAIN_NUMA, propertiesCallback[1]); + EXPECT_EQ(0, propertiesCallback[2]); + + EXPECT_STREQ("clCreateSubDevices", callbackData->functionName); + EXPECT_EQ(CL_SUCCESS, *reinterpret_cast(callbackData->functionReturnValue)); + ++exitCount; + } + } + + protected: + DebugManagerStateRestore restorer; + std::unique_ptr device; + cl_device_partition_property properties[3] = {CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN, CL_DEVICE_AFFINITY_DOMAIN_NUMA, 0}; + cl_uint deviceCount = 2u; + cl_device_id outDevices[2] = {0, 0}; + cl_uint numDevicesRet[1] = {0u}; + + uint16_t enterCount = 0u; + uint16_t exitCount = 0u; +}; + +TEST_F(IntelClCreateSubDevicesTracingTest, givenCreateSubDevicesCallTracingEnabledWhenInvokingThisCallThenCallIsSuccessfullyTraced) { + call(); + EXPECT_EQ(1u, enterCount); + EXPECT_EQ(1u, exitCount); +} + } // namespace ULT