[Piglit] [PATCH v2 1/2] cl: Add support for cl_half to program tester

Jan Vesely jan.vesely at rutgers.edu
Tue Aug 16 14:56:08 UTC 2016


On Sat, 2016-08-06 at 14:47 -0400, Jan Vesely wrote:
> 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,  floa
> t_array)
>  		CASE(TYPE_FLOAT,  cl_float,   get_float_array,  floa
> t_array)
> -		CASE(TYPE_DOUBLE,  cl_double,   get_float_array,  fl
> oat_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_ty
> pe*)test_arg.value)[rb], \
> +				                             test_ar
> g.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.
>   */

ping

-- 
Jan Vesely <jan.vesely at rutgers.edu>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <https://lists.freedesktop.org/archives/piglit/attachments/20160816/e5b75cce/attachment.sig>


More information about the Piglit mailing list