mirror of
https://github.com/KhronosGroup/OpenCL-CTS.git
synced 2026-03-19 06:09:01 +00:00
add system SVM testing via clSVMAllocWithProperties (#2516)
This PR adds system SVM testing both using driver APIs (`clSVMAllocWithPropertiesKHR`) and the system allocator directly (e.g. `malloc`). This is done by finding all of the SVM capabilities that are "system allocated" and duplicating them with a special "use system allocator" pseudo-capability. When the "use system allocator" pseudo-capability is not present, the system SVM type is treated the same as all other unified SVM types and is tested using driver APIs. When the "use system allocator" pseudo-capability is present, the system SVM type is allocated using the system allocator directly, though this also adds some limitations, for example the properties of the allocation may not be queried using `clGetSVMPointerInfoKHR`. See discussion in: https://github.com/KhronosGroup/OpenCL-Docs/issues/1446
This commit is contained in:
@@ -37,6 +37,13 @@ struct UnifiedSVMAPISuggestedTypeIndex : UnifiedSVMBase
|
|||||||
cl_svm_capabilities_khr allSupportedDeviceUSVMCaps = 0;
|
cl_svm_capabilities_khr allSupportedDeviceUSVMCaps = 0;
|
||||||
for (const auto caps : deviceUSVMCaps)
|
for (const auto caps : deviceUSVMCaps)
|
||||||
{
|
{
|
||||||
|
if (caps & PSEUDO_CAPABILITY_USE_SYSTEM_ALLOCATOR)
|
||||||
|
{
|
||||||
|
// The system allocator pseudo-capability is not a real
|
||||||
|
// capability, so skip it.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
err = checkSuggestedTypeIndex(caps, size);
|
err = checkSuggestedTypeIndex(caps, size);
|
||||||
test_error(err, "suggested type index failed");
|
test_error(err, "suggested type index failed");
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ struct UnifiedSVMAPIs : UnifiedSVMBase
|
|||||||
// that support CL_SVM_CAPABILITY_DEVICE_UNASSOCIATED_KHR, as long as
|
// that support CL_SVM_CAPABILITY_DEVICE_UNASSOCIATED_KHR, as long as
|
||||||
// this is not a system allocated type.
|
// this is not a system allocated type.
|
||||||
if (caps & CL_SVM_CAPABILITY_DEVICE_UNASSOCIATED_KHR
|
if (caps & CL_SVM_CAPABILITY_DEVICE_UNASSOCIATED_KHR
|
||||||
&& !(caps & CL_SVM_CAPABILITY_SYSTEM_ALLOCATED_KHR))
|
&& !(caps & PSEUDO_CAPABILITY_USE_SYSTEM_ALLOCATOR))
|
||||||
{
|
{
|
||||||
std::vector<cl_svm_alloc_properties_khr> props;
|
std::vector<cl_svm_alloc_properties_khr> props;
|
||||||
props.push_back(CL_SVM_ALLOC_ASSOCIATED_DEVICE_HANDLE_KHR);
|
props.push_back(CL_SVM_ALLOC_ASSOCIATED_DEVICE_HANDLE_KHR);
|
||||||
@@ -83,7 +83,7 @@ struct UnifiedSVMAPIs : UnifiedSVMBase
|
|||||||
// this is not a system allocated type.
|
// this is not a system allocated type.
|
||||||
// !!! Check: Is this a valid test?
|
// !!! Check: Is this a valid test?
|
||||||
if (caps & CL_SVM_CAPABILITY_DEVICE_UNASSOCIATED_KHR
|
if (caps & CL_SVM_CAPABILITY_DEVICE_UNASSOCIATED_KHR
|
||||||
&& !(caps & CL_SVM_CAPABILITY_SYSTEM_ALLOCATED_KHR))
|
&& !(caps & PSEUDO_CAPABILITY_USE_SYSTEM_ALLOCATOR))
|
||||||
{
|
{
|
||||||
std::vector<cl_svm_alloc_properties_khr> props;
|
std::vector<cl_svm_alloc_properties_khr> props;
|
||||||
props.push_back(CL_SVM_ALLOC_ASSOCIATED_DEVICE_HANDLE_KHR);
|
props.push_back(CL_SVM_ALLOC_ASSOCIATED_DEVICE_HANDLE_KHR);
|
||||||
@@ -108,7 +108,7 @@ struct UnifiedSVMAPIs : UnifiedSVMBase
|
|||||||
// CL_SVM_CAPABILITY_DEVICE_UNASSOCIATED_KHR, as long as this is not a
|
// CL_SVM_CAPABILITY_DEVICE_UNASSOCIATED_KHR, as long as this is not a
|
||||||
// system allocated type.
|
// system allocated type.
|
||||||
if (caps & CL_SVM_CAPABILITY_DEVICE_UNASSOCIATED_KHR
|
if (caps & CL_SVM_CAPABILITY_DEVICE_UNASSOCIATED_KHR
|
||||||
&& !(caps & CL_SVM_CAPABILITY_SYSTEM_ALLOCATED_KHR))
|
&& !(caps & PSEUDO_CAPABILITY_USE_SYSTEM_ALLOCATOR))
|
||||||
{
|
{
|
||||||
std::vector<cl_svm_alloc_properties_khr> props;
|
std::vector<cl_svm_alloc_properties_khr> props;
|
||||||
props.push_back(0);
|
props.push_back(0);
|
||||||
@@ -237,7 +237,7 @@ struct UnifiedSVMAPIs : UnifiedSVMBase
|
|||||||
cl_int err;
|
cl_int err;
|
||||||
|
|
||||||
// We cannot test queries for system allocated memory.
|
// We cannot test queries for system allocated memory.
|
||||||
if (caps & CL_SVM_CAPABILITY_SYSTEM_ALLOCATED_KHR)
|
if (caps & PSEUDO_CAPABILITY_USE_SYSTEM_ALLOCATOR)
|
||||||
{
|
{
|
||||||
return CL_SUCCESS;
|
return CL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ struct UnifiedSVMCapabilities : UnifiedSVMBase
|
|||||||
cl_int test_CL_SVM_CAPABILITY_DEVICE_UNASSOCIATED_KHR(cl_uint typeIndex)
|
cl_int test_CL_SVM_CAPABILITY_DEVICE_UNASSOCIATED_KHR(cl_uint typeIndex)
|
||||||
{
|
{
|
||||||
const auto caps = deviceUSVMCaps[typeIndex];
|
const auto caps = deviceUSVMCaps[typeIndex];
|
||||||
if (caps & CL_SVM_CAPABILITY_SYSTEM_ALLOCATED_KHR)
|
if (caps & PSEUDO_CAPABILITY_USE_SYSTEM_ALLOCATOR)
|
||||||
{
|
{
|
||||||
return CL_SUCCESS;
|
return CL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,10 +189,7 @@ struct UnifiedSVMExecInfo : UnifiedSVMBase
|
|||||||
cl_int setup() override
|
cl_int setup() override
|
||||||
{
|
{
|
||||||
cl_int err = UnifiedSVMBase::setup();
|
cl_int err = UnifiedSVMBase::setup();
|
||||||
if (CL_SUCCESS != err)
|
test_error(err, "UnifiedSVMBase setup failed");
|
||||||
{
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return createIndirectAccessKernel();
|
return createIndirectAccessKernel();
|
||||||
}
|
}
|
||||||
@@ -209,19 +206,12 @@ struct UnifiedSVMExecInfo : UnifiedSVMBase
|
|||||||
err = mem->allocate(alloc_count);
|
err = mem->allocate(alloc_count);
|
||||||
test_error(err, "SVM allocation failed");
|
test_error(err, "SVM allocation failed");
|
||||||
|
|
||||||
log_info(" testing clSetKernelArgSVMPointer() SVM type %u \n",
|
log_info(" testing clSetKernelExecInfo() SVM type %u \n", ti);
|
||||||
ti);
|
|
||||||
err = test_svm_exec_info_read(mem.get());
|
err = test_svm_exec_info_read(mem.get());
|
||||||
if (CL_SUCCESS != err)
|
test_error(err, "test_svm_exec_info_read failed");
|
||||||
{
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = test_svm_exec_info_write(mem.get());
|
err = test_svm_exec_info_write(mem.get());
|
||||||
if (CL_SUCCESS != err)
|
test_error(err, "test_svm_exec_info_write failed");
|
||||||
{
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = mem->free();
|
err = mem->free();
|
||||||
test_error(err, "SVM free failed");
|
test_error(err, "SVM free failed");
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ void CL_CALLBACK callback_svm_free(cl_command_queue queue,
|
|||||||
{
|
{
|
||||||
data->svm_pointers[i] = svm_pointers[i];
|
data->svm_pointers[i] = svm_pointers[i];
|
||||||
|
|
||||||
if (data->svm_caps[i] & CL_SVM_CAPABILITY_SYSTEM_ALLOCATED_KHR)
|
if (data->svm_caps[i] & PSEUDO_CAPABILITY_USE_SYSTEM_ALLOCATOR)
|
||||||
{
|
{
|
||||||
align_free(data);
|
align_free(data);
|
||||||
}
|
}
|
||||||
@@ -169,13 +169,13 @@ struct UnifiedSVMFree : UnifiedSVMBase
|
|||||||
test_error(err, "test_SVMFree");
|
test_error(err, "test_SVMFree");
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to filter out the SVM types that support system allocation
|
// We need to filter out the SVM types that are system allocated
|
||||||
// as we cannot test clEnqueueSVMFree without a callback for them
|
// as we cannot test clEnqueueSVMFree without a callback for them
|
||||||
std::vector<size_t> test_indexes;
|
std::vector<size_t> test_indexes;
|
||||||
for (size_t i = 0; i < deviceUSVMCaps.size(); i++)
|
for (size_t i = 0; i < deviceUSVMCaps.size(); i++)
|
||||||
{
|
{
|
||||||
auto caps = deviceUSVMCaps[i];
|
auto caps = deviceUSVMCaps[i];
|
||||||
if (0 == (caps & CL_SVM_CAPABILITY_SYSTEM_ALLOCATED_KHR))
|
if (0 == (caps & PSEUDO_CAPABILITY_USE_SYSTEM_ALLOCATOR))
|
||||||
{
|
{
|
||||||
test_indexes.push_back(i);
|
test_indexes.push_back(i);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ struct UnifiedSVMOPs : UnifiedSVMBase
|
|||||||
|
|
||||||
// We check if the memory can be read by the host.
|
// We check if the memory can be read by the host.
|
||||||
if (caps & CL_SVM_CAPABILITY_HOST_READ_KHR
|
if (caps & CL_SVM_CAPABILITY_HOST_READ_KHR
|
||||||
|| caps & CL_SVM_CAPABILITY_SYSTEM_ALLOCATED_KHR)
|
|| caps & PSEUDO_CAPABILITY_USE_SYSTEM_ALLOCATOR)
|
||||||
{
|
{
|
||||||
err = test_SVMMemcpy(mem.get(), hostMem.get());
|
err = test_SVMMemcpy(mem.get(), hostMem.get());
|
||||||
test_error(err, "test_SVMMemcpy");
|
test_error(err, "test_SVMMemcpy");
|
||||||
@@ -143,7 +143,7 @@ struct UnifiedSVMOPs : UnifiedSVMBase
|
|||||||
|
|
||||||
// We check if the memory can be written by the host.
|
// We check if the memory can be written by the host.
|
||||||
if (caps & CL_SVM_CAPABILITY_HOST_WRITE_KHR
|
if (caps & CL_SVM_CAPABILITY_HOST_WRITE_KHR
|
||||||
|| caps & CL_SVM_CAPABILITY_SYSTEM_ALLOCATED_KHR)
|
|| caps & PSEUDO_CAPABILITY_USE_SYSTEM_ALLOCATOR)
|
||||||
{
|
{
|
||||||
err = test_SVMMemcpy(hostMem.get(), mem.get());
|
err = test_SVMMemcpy(hostMem.get(), mem.get());
|
||||||
test_error(err, "test_SVMMemcpy");
|
test_error(err, "test_SVMMemcpy");
|
||||||
@@ -162,7 +162,7 @@ struct UnifiedSVMOPs : UnifiedSVMBase
|
|||||||
cl_int err;
|
cl_int err;
|
||||||
cl_uint max_ti = static_cast<cl_uint>(deviceUSVMCaps.size());
|
cl_uint max_ti = static_cast<cl_uint>(deviceUSVMCaps.size());
|
||||||
|
|
||||||
// Test all possible comabinations between supported types
|
// Test all possible combinations between supported types
|
||||||
for (cl_uint src_ti = 0; src_ti < max_ti; src_ti++)
|
for (cl_uint src_ti = 0; src_ti < max_ti; src_ti++)
|
||||||
{
|
{
|
||||||
for (cl_uint dst_ti = 0; dst_ti < max_ti; dst_ti++)
|
for (cl_uint dst_ti = 0; dst_ti < max_ti; dst_ti++)
|
||||||
@@ -208,7 +208,7 @@ struct UnifiedSVMOPs : UnifiedSVMBase
|
|||||||
{
|
{
|
||||||
return std::unique_ptr<USVMWrapper<T>>(
|
return std::unique_ptr<USVMWrapper<T>>(
|
||||||
new USVMWrapper<T>(nullptr, nullptr, nullptr, CL_UINT_MAX,
|
new USVMWrapper<T>(nullptr, nullptr, nullptr, CL_UINT_MAX,
|
||||||
CL_SVM_CAPABILITY_SYSTEM_ALLOCATED_KHR
|
PSEUDO_CAPABILITY_USE_SYSTEM_ALLOCATOR
|
||||||
| CL_SVM_CAPABILITY_HOST_READ_KHR
|
| CL_SVM_CAPABILITY_HOST_READ_KHR
|
||||||
| CL_SVM_CAPABILITY_HOST_WRITE_KHR,
|
| CL_SVM_CAPABILITY_HOST_WRITE_KHR,
|
||||||
0, nullptr, nullptr, nullptr, nullptr));
|
0, nullptr, nullptr, nullptr, nullptr));
|
||||||
@@ -216,7 +216,6 @@ struct UnifiedSVMOPs : UnifiedSVMBase
|
|||||||
|
|
||||||
bool caps_compatibility_check(cl_uint srcTypeIndex, cl_uint dstTypeIndex)
|
bool caps_compatibility_check(cl_uint srcTypeIndex, cl_uint dstTypeIndex)
|
||||||
{
|
{
|
||||||
|
|
||||||
const auto srcCaps = deviceUSVMCaps[srcTypeIndex];
|
const auto srcCaps = deviceUSVMCaps[srcTypeIndex];
|
||||||
const auto dstCaps = deviceUSVMCaps[dstTypeIndex];
|
const auto dstCaps = deviceUSVMCaps[dstTypeIndex];
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,9 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
constexpr cl_bitfield PSEUDO_CAPABILITY_USE_SYSTEM_ALLOCATOR =
|
||||||
|
((cl_bitfield)1 << 63);
|
||||||
|
|
||||||
static inline void parseSVMAllocProperties(
|
static inline void parseSVMAllocProperties(
|
||||||
std::vector<cl_svm_alloc_properties_khr> props, cl_device_id& device,
|
std::vector<cl_svm_alloc_properties_khr> props, cl_device_id& device,
|
||||||
cl_svm_alloc_access_flags_khr& accessFlags, size_t& alignment)
|
cl_svm_alloc_access_flags_khr& accessFlags, size_t& alignment)
|
||||||
@@ -82,7 +85,7 @@ public:
|
|||||||
free();
|
free();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (caps & CL_SVM_CAPABILITY_SYSTEM_ALLOCATED_KHR)
|
if (caps & PSEUDO_CAPABILITY_USE_SYSTEM_ALLOCATOR)
|
||||||
{
|
{
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
{
|
{
|
||||||
@@ -135,7 +138,7 @@ public:
|
|||||||
{
|
{
|
||||||
if (data)
|
if (data)
|
||||||
{
|
{
|
||||||
if (caps & CL_SVM_CAPABILITY_SYSTEM_ALLOCATED_KHR)
|
if (caps & PSEUDO_CAPABILITY_USE_SYSTEM_ALLOCATOR)
|
||||||
{
|
{
|
||||||
align_free(data);
|
align_free(data);
|
||||||
}
|
}
|
||||||
@@ -317,6 +320,42 @@ struct UnifiedSVMBase
|
|||||||
err,
|
err,
|
||||||
"clGetDeviceInfo failed for CL_DEVICE_SVM_CAPABILITIES_KHR data");
|
"clGetDeviceInfo failed for CL_DEVICE_SVM_CAPABILITIES_KHR data");
|
||||||
|
|
||||||
|
test_assert_error(platformUSVMCaps.size() == deviceUSVMCaps.size(),
|
||||||
|
"Platform SVM capability size does not match device "
|
||||||
|
"SVM capability size!");
|
||||||
|
|
||||||
|
const size_t check = platformUSVMCaps.size();
|
||||||
|
|
||||||
|
// Look through the platform and device SVM capabilities.
|
||||||
|
// If our pseudo capability to indicate that the system allocator should
|
||||||
|
// be used is reported as a real capability, then we can't continue
|
||||||
|
// testing.
|
||||||
|
for (size_t ti = 0; ti < check; ti++)
|
||||||
|
{
|
||||||
|
auto caps = deviceUSVMCaps[ti];
|
||||||
|
if (caps & PSEUDO_CAPABILITY_USE_SYSTEM_ALLOCATOR)
|
||||||
|
{
|
||||||
|
log_info("Unable to continue, device reports system allocator "
|
||||||
|
"pseudo-capability as an SVM capability.\n");
|
||||||
|
return CL_INVALID_OPERATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For any capabilities that support the system allocator, add a
|
||||||
|
// scenario testing with the system allocator vs. allocating via OpenCL.
|
||||||
|
for (size_t ti = 0; ti < check; ti++)
|
||||||
|
{
|
||||||
|
if (deviceUSVMCaps[ti] & CL_SVM_CAPABILITY_SYSTEM_ALLOCATED_KHR)
|
||||||
|
{
|
||||||
|
deviceUSVMCaps.push_back(
|
||||||
|
deviceUSVMCaps[ti]
|
||||||
|
| PSEUDO_CAPABILITY_USE_SYSTEM_ALLOCATOR);
|
||||||
|
platformUSVMCaps.push_back(
|
||||||
|
platformUSVMCaps[ti]
|
||||||
|
| PSEUDO_CAPABILITY_USE_SYSTEM_ALLOCATOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
clSVMAllocWithPropertiesKHR = (clSVMAllocWithPropertiesKHR_fn)
|
clSVMAllocWithPropertiesKHR = (clSVMAllocWithPropertiesKHR_fn)
|
||||||
clGetExtensionFunctionAddressForPlatform(
|
clGetExtensionFunctionAddressForPlatform(
|
||||||
platform, "clSVMAllocWithPropertiesKHR");
|
platform, "clSVMAllocWithPropertiesKHR");
|
||||||
|
|||||||
Reference in New Issue
Block a user