Skip to content

Commit 9d3ae4c

Browse files
authored
Added support for cl_ext_float_atomics in CBasicTestFetchAddSpecialFloats with atomic_float (#2371)
Related to #2142, according to the work plan, extending CBasicTestFetchAddSpecialFloats with support for atomic_float.
1 parent 50ba8c8 commit 9d3ae4c

3 files changed

Lines changed: 132 additions & 24 deletions

File tree

test_conformance/c11_atomics/common.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@
2222

2323
#include "host_atomics.h"
2424

25-
#include "CL/cl_half.h"
26-
2725
#include <iomanip>
2826
#include <limits>
2927
#include <sstream>
3028
#include <vector>
3129

30+
#include "CL/cl_half.h"
31+
3232
#define MAX_DEVICE_THREADS (gHost ? 0U : gMaxDeviceThreads)
3333
#define MAX_HOST_THREADS GetThreadCount()
3434

@@ -76,9 +76,8 @@ extern int
7676
gMaxDeviceThreads; // maximum number of threads executed on OCL device
7777
extern cl_device_atomic_capabilities gAtomicMemCap,
7878
gAtomicFenceCap; // atomic memory and fence capabilities for this device
79-
extern cl_half_rounding_mode gHalfRoundingMode;
80-
extern bool gFloatAtomicsSupported;
81-
extern cl_device_fp_atomic_capabilities_ext gHalfAtomicCaps;
79+
80+
extern cl_device_fp_config gFloatFPConfig;
8281
extern cl_device_fp_config gHalfFPConfig;
8382

8483
extern cl_half_rounding_mode gHalfRoundingMode;
@@ -183,6 +182,7 @@ class CBasicTest : CTest {
183182
{
184183
return false;
185184
}
185+
186186
virtual bool
187187
IsTestNotAsExpected(const HostDataType &expected,
188188
const std::vector<HostAtomicType> &testValues,
@@ -926,7 +926,14 @@ CBasicTest<HostAtomicType, HostDataType>::ProgramHeader(cl_uint maxNumDestItems)
926926

927927
if constexpr (std::is_same_v<HostDataType, HOST_FLOAT>)
928928
{
929-
ss << std::setprecision(10) << _startValue;
929+
if (std::isinf(_startValue))
930+
ss << (_startValue < 0 ? "-" : "") << "INFINITY";
931+
else if (std::isnan(_startValue))
932+
ss << "0.0f / 0.0f";
933+
else
934+
ss << std::setprecision(
935+
std::numeric_limits<HostDataType>::max_digits10)
936+
<< _startValue;
930937
}
931938
else if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
932939
{

test_conformance/c11_atomics/main.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ int gInternalIterations = 10000; // internal test iterations for atomic operatio
3131
int gMaxDeviceThreads = 1024; // maximum number of threads executed on OCL device
3232
cl_device_atomic_capabilities gAtomicMemCap,
3333
gAtomicFenceCap; // atomic memory and fence capabilities for this device
34+
35+
cl_device_fp_config gFloatFPConfig = 0;
3436
cl_half_rounding_mode gHalfRoundingMode = CL_HALF_RTE;
3537
bool gFloatAtomicsSupported = false;
3638
cl_device_fp_atomic_capabilities_ext gHalfAtomicCaps = 0;
@@ -148,6 +150,13 @@ test_status InitCL(cl_device_id device) {
148150
sizeof(gFloatAtomicCaps), &gFloatAtomicCaps, nullptr);
149151
test_error_ret(error, "clGetDeviceInfo failed!", TEST_FAIL);
150152

153+
error = clGetDeviceInfo(device, CL_DEVICE_SINGLE_FP_CONFIG,
154+
sizeof(gFloatFPConfig), &gFloatFPConfig, NULL);
155+
test_error_ret(
156+
error,
157+
"Unable to run INFINITY/NAN tests (unable to get FP_CONFIG bits)",
158+
TEST_FAIL);
159+
151160
if (is_extension_available(device, "cl_khr_fp16"))
152161
{
153162
cl_int error = clGetDeviceInfo(

test_conformance/c11_atomics/test_atomics.cpp

Lines changed: 110 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,13 +1437,21 @@ class CBasicTestFetchAddSpecialFloats
14371437
: CBasicTestMemOrderScope<HostAtomicType, HostDataType>(dataType,
14381438
useSVM)
14391439
{
1440-
if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1440+
// StartValue is used as an index divisor in the following test
1441+
// logic. It is set to the number of special values, which allows
1442+
// threads to be mapped deterministically onto the input data array.
1443+
// This enables repeated add operations arranged so that every
1444+
// special value is added to every other one (“all-to-all”).
1445+
1446+
if constexpr (std::is_same_v<HostDataType, HOST_FLOAT>)
1447+
{
1448+
auto spec_vals = GetSpecialValues();
1449+
StartValue(spec_vals.size());
1450+
CBasicTestMemOrderScope<HostAtomicType,
1451+
HostDataType>::OldValueCheck(false);
1452+
}
1453+
else if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
14411454
{
1442-
// StartValue is used as an index divisor in the following test
1443-
// logic. It is set to the number of special values, which allows
1444-
// threads to be mapped deterministically onto the input data array.
1445-
// This enables repeated add operations arranged so that every
1446-
// special value is added to every other one (“all-to-all”).
14471455

14481456
auto spec_vals = GetSpecialValues();
14491457
StartValue(cl_half_from_float(spec_vals.size(), gHalfRoundingMode));
@@ -1454,10 +1462,42 @@ class CBasicTestFetchAddSpecialFloats
14541462

14551463
static std::vector<HostDataType> &GetSpecialValues()
14561464
{
1465+
const float test_value_zero = 0.0f;
1466+
const float test_value_minus_zero = -0.0f;
1467+
const float test_value_without_fraction = 2.0f;
1468+
const float test_value_with_fraction = 2.2f;
1469+
14571470
static std::vector<HostDataType> special_values;
1458-
if (special_values.empty())
1471+
if constexpr (std::is_same_v<HostDataType, HOST_FLOAT>)
14591472
{
1460-
if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1473+
if (special_values.empty())
1474+
{
1475+
special_values = {
1476+
static_cast<HostDataType>(test_value_minus_zero),
1477+
static_cast<HostDataType>(test_value_zero),
1478+
static_cast<HostDataType>(test_value_without_fraction),
1479+
static_cast<HostDataType>(test_value_with_fraction),
1480+
std::numeric_limits<HostDataType>::infinity(),
1481+
std::numeric_limits<HostDataType>::quiet_NaN(),
1482+
std::numeric_limits<HostDataType>::signaling_NaN(),
1483+
-std::numeric_limits<HostDataType>::infinity(),
1484+
-std::numeric_limits<HostDataType>::quiet_NaN(),
1485+
-std::numeric_limits<HostDataType>::signaling_NaN(),
1486+
std::numeric_limits<HostDataType>::lowest(),
1487+
std::numeric_limits<HostDataType>::min(),
1488+
std::numeric_limits<HostDataType>::max(),
1489+
};
1490+
1491+
if (0 != (CL_FP_DENORM & gFloatFPConfig))
1492+
{
1493+
special_values.push_back(
1494+
std::numeric_limits<HostDataType>::denorm_min());
1495+
}
1496+
}
1497+
}
1498+
else if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1499+
{
1500+
if (special_values.empty())
14611501
{
14621502
special_values = {
14631503
0xffff, 0x0000, 0x7c00, /*INFINITY*/
@@ -1491,7 +1531,10 @@ class CBasicTestFetchAddSpecialFloats
14911531
bool GenerateRefs(cl_uint threadCount, HostDataType *startRefValues,
14921532
MTdata d) override
14931533
{
1494-
if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1534+
if constexpr (
1535+
std::is_same_v<
1536+
HostDataType,
1537+
HOST_HALF> || std::is_same_v<HostDataType, HOST_FLOAT>)
14951538
{
14961539
if (threadCount > ref_vals.size())
14971540
{
@@ -1522,7 +1565,10 @@ class CBasicTestFetchAddSpecialFloats
15221565
std::string memoryOrderScope = MemoryOrderScopeStr();
15231566
std::string postfix(memoryOrderScope.empty() ? "" : "_explicit");
15241567

1525-
if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1568+
if constexpr (
1569+
std::is_same_v<
1570+
HostDataType,
1571+
HOST_HALF> || std::is_same_v<HostDataType, HOST_FLOAT>)
15261572
{
15271573
// The start_value variable (set by StartValue) is used
15281574
// as a divisor of the thread index when selecting the operand for
@@ -1548,7 +1594,10 @@ class CBasicTestFetchAddSpecialFloats
15481594
volatile HostAtomicType *destMemory,
15491595
HostDataType *oldValues) override
15501596
{
1551-
if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1597+
if constexpr (
1598+
std::is_same_v<
1599+
HostDataType,
1600+
HOST_HALF> || std::is_same_v<HostDataType, HOST_FLOAT>)
15521601
{
15531602
auto spec_vals = GetSpecialValues();
15541603
host_atomic_store(&destMemory[tid], (HostDataType)oldValues[tid],
@@ -1563,7 +1612,14 @@ class CBasicTestFetchAddSpecialFloats
15631612
cl_uint whichDestValue) override
15641613
{
15651614
expected = StartValue();
1566-
if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1615+
1616+
if constexpr (std::is_same_v<HostDataType, HOST_FLOAT>)
1617+
{
1618+
auto spec_vals = GetSpecialValues();
1619+
expected = startRefValues[whichDestValue]
1620+
+ startRefValues[whichDestValue / spec_vals.size()];
1621+
}
1622+
else if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
15671623
{
15681624
auto spec_vals = GetSpecialValues();
15691625
expected = cl_half_from_float(
@@ -1575,13 +1631,18 @@ class CBasicTestFetchAddSpecialFloats
15751631

15761632
return true;
15771633
}
1578-
15791634
bool IsTestNotAsExpected(const HostDataType &expected,
15801635
const std::vector<HostAtomicType> &testValues,
15811636
cl_uint whichDestValue) override
15821637
{
1583-
1584-
if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1638+
if constexpr (std::is_same_v<HostDataType, HOST_FLOAT>)
1639+
{
1640+
if (std::isnan(testValues[whichDestValue]) && std::isnan(expected))
1641+
return false;
1642+
else
1643+
return expected != testValues[whichDestValue];
1644+
}
1645+
else if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
15851646
{
15861647
return static_cast<cl_half>(expected) != testValues[whichDestValue];
15871648
}
@@ -1591,11 +1652,28 @@ class CBasicTestFetchAddSpecialFloats
15911652
testValues,
15921653
whichDestValue);
15931654
}
1594-
15951655
int ExecuteSingleTest(cl_device_id deviceID, cl_context context,
15961656
cl_command_queue queue) override
15971657
{
1598-
if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1658+
if constexpr (std::is_same_v<HostDataType, HOST_FLOAT>)
1659+
{
1660+
if (LocalMemory()
1661+
&& (gFloatAtomicCaps & CL_DEVICE_LOCAL_FP_ATOMIC_ADD_EXT) == 0)
1662+
return 0; // skip test - not applicable
1663+
1664+
if (!LocalMemory()
1665+
&& (gFloatAtomicCaps & CL_DEVICE_GLOBAL_FP_ATOMIC_ADD_EXT) == 0)
1666+
return 0;
1667+
1668+
if (!CBasicTestMemOrderScope<HostAtomicType,
1669+
HostDataType>::LocalMemory()
1670+
&& CBasicTestMemOrderScope<HostAtomicType,
1671+
HostDataType>::DeclaredInProgram())
1672+
{
1673+
if ((gFloatFPConfig & CL_FP_INF_NAN) == 0) return 0;
1674+
}
1675+
}
1676+
else if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
15991677
{
16001678
if (DeclaredInProgram()) return 0; // skip test - not applicable
16011679

@@ -1621,7 +1699,10 @@ class CBasicTestFetchAddSpecialFloats
16211699
}
16221700
cl_uint NumResults(cl_uint threadCount, cl_device_id deviceID) override
16231701
{
1624-
if constexpr (std::is_same_v<HostDataType, HOST_HALF>)
1702+
if constexpr (
1703+
std::is_same_v<
1704+
HostDataType,
1705+
HOST_HALF> || std::is_same_v<HostDataType, HOST_FLOAT>)
16251706
{
16261707
return threadCount;
16271708
}
@@ -1656,6 +1737,17 @@ static int test_atomic_fetch_add_generic(cl_device_id deviceID,
16561737

16571738
if (gFloatAtomicsSupported)
16581739
{
1740+
auto spec_vals_fp32 =
1741+
CBasicTestFetchAddSpecialFloats<HOST_ATOMIC_FLOAT,
1742+
HOST_FLOAT>::GetSpecialValues();
1743+
1744+
CBasicTestFetchAddSpecialFloats<HOST_ATOMIC_FLOAT, HOST_FLOAT>
1745+
test_spec_float(TYPE_ATOMIC_FLOAT, useSVM);
1746+
EXECUTE_TEST(error,
1747+
test_spec_float.Execute(deviceID, context, queue,
1748+
spec_vals_fp32.size()
1749+
* spec_vals_fp32.size()));
1750+
16591751
auto spec_vals_halfs =
16601752
CBasicTestFetchAddSpecialFloats<HOST_ATOMIC_HALF,
16611753
HOST_HALF>::GetSpecialValues();

0 commit comments

Comments
 (0)