[Piglit] [PATCH v2 1/2] cl: Add support for cl_half to program tester
Jan Vesely
jan.vesely at rutgers.edu
Sat Aug 6 18:47:22 UTC 2016
Use explicit conversion from regexp matched array values
v2: distance between two half numbers is 8192 single float ulps
no need to place converted float in the middle of single precision range
Signed-off-by: Jan Vesely <jan.vesely at rutgers.edu>
---
tests/cl/program/program-tester.c | 31 ++++++++++++++++++++++++++----
tests/util/piglit-util-cl.c | 40 +++++++++++++++++++++++++++++++++++++++
tests/util/piglit-util-cl.h | 25 ++++++++++++++++++++++++
3 files changed, 92 insertions(+), 4 deletions(-)
diff --git a/tests/cl/program/program-tester.c b/tests/cl/program/program-tester.c
index 8e3cb4d..25b677f 100644
--- a/tests/cl/program/program-tester.c
+++ b/tests/cl/program/program-tester.c
@@ -111,12 +111,14 @@
// TODO: probably we could use libmpdec to handle this
// http://www.bytereef.org/mpdecimal/index.html
//#define REGEX_TYPE_HALF "buffer half[1]"
+#define REGEX_TYPE_HALF REGEX_DEFINE_TYPE("half")
#define REGEX_TYPE_FLOAT REGEX_DEFINE_TYPE("float")
#define REGEX_TYPE_DOUBLE REGEX_DEFINE_TYPE("double")
#define REGEX_TYPE REGEX_TYPE_CHAR "|" REGEX_TYPE_UCHAR "|" \
REGEX_TYPE_SHORT "|" REGEX_TYPE_USHORT "|" \
- REGEX_TYPE_INT "|" REGEX_TYPE_UINT "|" REGEX_TYPE_LONG "|" \
- REGEX_TYPE_ULONG "|" REGEX_TYPE_FLOAT "|" REGEX_TYPE_DOUBLE
+ REGEX_TYPE_INT "|" REGEX_TYPE_UINT "|" \
+ REGEX_TYPE_LONG "|" REGEX_TYPE_ULONG "|" \
+ REGEX_TYPE_HALF "|" REGEX_TYPE_FLOAT "|" REGEX_TYPE_DOUBLE
/* Image types */
/* TODO: add OpenCL 1.2+ types */
@@ -324,6 +326,7 @@ enum cl_type {
TYPE_UINT,
TYPE_LONG,
TYPE_ULONG,
+ TYPE_HALF,
TYPE_FLOAT,
TYPE_DOUBLE,
};
@@ -1002,7 +1005,7 @@ get_test_arg_value(struct test_arg* test_arg, const char* value, size_t length)
for(c = 0; c < test_arg->cl_size; c++) { \
ra = i*test_arg->cl_size + c; \
rb = i*test_arg->cl_mem_size + c; \
- ((cl_type*)test_arg->value)[rb] = array[ra%length]; \
+ ((cl_type*)test_arg->value)[rb] = convert_##cl_type(array[ra%length]); \
} \
} \
break;
@@ -1016,8 +1019,9 @@ get_test_arg_value(struct test_arg* test_arg, const char* value, size_t length)
CASE(TYPE_UINT, cl_uint, get_uint_array, uint_array)
CASE(TYPE_LONG, cl_long, get_int_array, int_array)
CASE(TYPE_ULONG, cl_ulong, get_uint_array, uint_array)
+ CASE(TYPE_HALF, cl_half, get_float_array, float_array)
CASE(TYPE_FLOAT, cl_float, get_float_array, float_array)
- CASE(TYPE_DOUBLE, cl_double, get_float_array, float_array)
+ CASE(TYPE_DOUBLE, cl_double, get_float_array, float_array)
}
#undef CASE
@@ -1040,6 +1044,7 @@ get_test_arg_tolerance(struct test_arg* test_arg, const char* tolerance_str)
REG_NEWLINE)) {
regex_get_match_str(&value_str, tolerance_str, pmatch, 1);
switch(test_arg->cl_type) {
+ case TYPE_HALF:
case TYPE_FLOAT:
case TYPE_DOUBLE:
test_arg->ulp = get_uint(value_str);
@@ -1070,6 +1075,7 @@ get_test_arg_tolerance(struct test_arg* test_arg, const char* tolerance_str)
case TYPE_ULONG:
test_arg->tolu = get_uint(value_str);
break;
+ case TYPE_HALF:
case TYPE_FLOAT:
case TYPE_DOUBLE: {
float value = get_float(value_str);
@@ -1152,6 +1158,7 @@ get_test_arg(const char* src, struct test* test, bool arg_in)
ELSEIF(REGEX_TYPE_UINT, TYPE_UINT, cl_uint)
ELSEIF(REGEX_TYPE_LONG, TYPE_LONG, cl_long)
ELSEIF(REGEX_TYPE_ULONG, TYPE_ULONG, cl_ulong)
+ ELSEIF(REGEX_TYPE_HALF, TYPE_HALF, cl_half)
ELSEIF(REGEX_TYPE_FLOAT, TYPE_FLOAT, cl_float)
ELSEIF(REGEX_TYPE_DOUBLE, TYPE_DOUBLE, cl_double)
@@ -2093,6 +2100,21 @@ check_test_arg_value(struct test_arg test_arg,
} \
} \
return true;
+#define CASEH(enum_type, type, cl_type) \
+ case enum_type: \
+ for(i = 0; i < test_arg.length; i++) { \
+ for(c = 0; c < test_arg.cl_size; c++) { \
+ rb = i*test_arg.cl_mem_size + c; \
+ if(!piglit_cl_probe_half(((cl_type*)value)[rb], \
+ ((cl_type*)test_arg.value)[rb], \
+ test_arg.ulp)) { \
+ ra = i*test_arg.cl_size + c; \
+ printf("Error at %s[%zu]\n", type, ra); \
+ return false; \
+ } \
+ } \
+ } \
+ return true;
#define CASEF(enum_type, type, cl_type) \
case enum_type: \
for(i = 0; i < test_arg.length; i++) { \
@@ -2118,6 +2140,7 @@ check_test_arg_value(struct test_arg test_arg,
CASEU(TYPE_UINT, "uint", cl_uint)
CASEI(TYPE_LONG, "long", cl_long)
CASEU(TYPE_ULONG, "ulong", cl_ulong)
+ CASEH(TYPE_HALF, "half", cl_half)
CASEF(TYPE_FLOAT, "float", cl_float)
CASEF(TYPE_DOUBLE, "double", cl_double)
}
diff --git a/tests/util/piglit-util-cl.c b/tests/util/piglit-util-cl.c
index 7e7d985..fb32fee 100644
--- a/tests/util/piglit-util-cl.c
+++ b/tests/util/piglit-util-cl.c
@@ -59,6 +59,27 @@ piglit_cl_probe_uinteger(uint64_t value, uint64_t expect, uint64_t tolerance)
((isnan(value) && isnan(expect)) || \
(isinf(value) && isinf(expect) && ((value > 0) == (expect > 0))))
+static float float_from_cl_half(uint32_t in)
+{
+ union {
+ uint32_t bits;
+ float val;
+ } convert;
+ uint32_t exponent = ((in >> 10) & 0x1f);
+ convert.bits = (((in >> 15) & 0x1) << 31) | //sign
+ ((exponent ? (exponent != 0x1f ? exponent + 112 : 0xff)
+ : 0) << 23) | //exponent (0 and 1f are special cases)
+ (((in >> 0) & 0x3ff) << 13); // mantissa
+ return convert.val;
+}
+
+bool piglit_cl_probe_half(cl_half value, cl_half expect, uint32_t ulp)
+{
+ // after conversion to float the last 13 digits are 0, adjust ulp
+ return piglit_cl_probe_floating(float_from_cl_half(value),
+ float_from_cl_half(expect),
+ ulp * 8192);
+}
/* TODO: Tolerance should be specified in terms of ULP. */
bool
@@ -118,6 +139,25 @@ piglit_cl_probe_double(double value, double expect, uint64_t ulp)
}
+cl_half convert_cl_half(double in)
+{
+ union {
+ uint64_t bits;
+ double val;
+ } convert = { .val = in };
+ /* Bit 63 is sign bit */
+ cl_half sign = (cl_half)((convert.bits >> 63) << 15);
+ /* Get only the top 10 bits of mantissa */
+ cl_half mantissa = (cl_half)((convert.bits >> 42) & 0x3ff);
+ /* 11 bits of exponent */
+ uint64_t exp = (convert.bits >> 52) & 0x7ff;
+ /* 0 and ~0 are special cases that are not adjusted,
+ * half bias is 15, double bias is 1023 */
+ cl_half exponent = ((exp == 0 || exp == 0x7ff) ? (exp & 0x3ff) :
+ (exp - 1008)) << 10;
+ return (sign | exponent | mantissa);
+}
+
bool
piglit_cl_check_error(cl_int error, cl_int expected_error)
{
diff --git a/tests/util/piglit-util-cl.h b/tests/util/piglit-util-cl.h
index 9fb4f9f..bd9f5a8 100644
--- a/tests/util/piglit-util-cl.h
+++ b/tests/util/piglit-util-cl.h
@@ -44,6 +44,25 @@
extern "C" {
#endif
+#define DIRECT_CONVERT(to, from) \
+static inline from convert_##to(from in) \
+{ \
+ return (to)in; \
+}
+
+DIRECT_CONVERT(cl_char, int64_t);
+DIRECT_CONVERT(cl_uchar, uint64_t);
+DIRECT_CONVERT(cl_short, int64_t);
+DIRECT_CONVERT(cl_ushort, uint64_t);
+DIRECT_CONVERT(cl_int, int64_t);
+DIRECT_CONVERT(cl_uint, uint64_t);
+DIRECT_CONVERT(cl_long, int64_t);
+DIRECT_CONVERT(cl_ulong, uint64_t);
+DIRECT_CONVERT(cl_float, double);
+DIRECT_CONVERT(cl_double, double);
+
+cl_half convert_cl_half(double in);
+
/* Runtime independent */
@@ -62,6 +81,12 @@ bool piglit_cl_probe_uinteger(uint64_t value,
uint64_t tolerance);
/**
+ * \brief Probe half-floating-point \c value if it compares equal to \c expect with
+ * tolerance \c ulp.
+ */
+bool piglit_cl_probe_half(cl_half value, cl_half expect, uint32_t ulp);
+
+/**
* \brief Probe floating-point \c value if it compares equal to \c expect with
* tolerance \c ulp.
*/
--
2.7.4
More information about the Piglit
mailing list