[Beignet] [PATCH V2 1/9] Utest: Move half related helper function into utest helper
Xiuli Pan
xiuli.pan at intel.com
Mon Aug 8 03:31:19 UTC 2016
From: Pan Xiuli <xiuli.pan at intel.com>
For more half related tests, need to use helper funciton in utest.
Signed-off-by: Pan Xiuli <xiuli.pan at intel.com>
---
utests/compiler_half.cpp | 155 ++++++-----------------------------------------
utests/utest_helper.cpp | 119 ++++++++++++++++++++++++++++++++++++
utests/utest_helper.hpp | 7 +++
3 files changed, 144 insertions(+), 137 deletions(-)
diff --git a/utests/compiler_half.cpp b/utests/compiler_half.cpp
index 3af1925..2b4ea2e 100644
--- a/utests/compiler_half.cpp
+++ b/utests/compiler_half.cpp
@@ -2,127 +2,8 @@
#include <cstring>
#include <iostream>
#include <cmath>
-#include <algorithm>
#include "utest_helper.hpp"
-static uint32_t __half_to_float(uint16_t h, bool* isInf = NULL, bool* infSign = NULL)
-{
- struct __FP32 {
- uint32_t mantissa:23;
- uint32_t exponent:8;
- uint32_t sign:1;
- };
- struct __FP16 {
- uint32_t mantissa:10;
- uint32_t exponent:5;
- uint32_t sign:1;
- };
- uint32_t f;
- __FP32 o;
- memset(&o, 0, sizeof(o));
- __FP16 i;
- memcpy(&i, &h, sizeof(uint16_t));
-
- if (isInf)
- *isInf = false;
- if (infSign)
- *infSign = false;
-
- if (i.exponent == 0 && i.mantissa == 0) // (Signed) zero
- o.sign = i.sign;
- else {
- if (i.exponent == 0) { // Denormal (converts to normalized)
- // Adjust mantissa so it's normalized (and keep
- // track of exponent adjustment)
- int e = -1;
- uint m = i.mantissa;
- do {
- e++;
- m <<= 1;
- } while ((m & 0x400) == 0);
-
- o.mantissa = (m & 0x3ff) << 13;
- o.exponent = 127 - 15 - e;
- o.sign = i.sign;
- } else if (i.exponent == 0x1f) { // Inf/NaN
- // NOTE: Both can be handled with same code path
- // since we just pass through mantissa bits.
- o.mantissa = i.mantissa << 13;
- o.exponent = 255;
- o.sign = i.sign;
-
- if (isInf) {
- *isInf = (i.mantissa == 0);
- if (infSign)
- *infSign = !i.sign;
- }
- } else { // Normalized number
- o.mantissa = i.mantissa << 13;
- o.exponent = 127 - 15 + i.exponent;
- o.sign = i.sign;
- }
- }
-
- memcpy(&f, &o, sizeof(uint32_t));
- return f;
-}
-
-
-static uint16_t __float_to_half(uint32_t x)
-{
- uint16_t bits = (x >> 16) & 0x8000; /* Get the sign */
- uint16_t m = (x >> 12) & 0x07ff; /* Keep one extra bit for rounding */
- unsigned int e = (x >> 23) & 0xff; /* Using int is faster here */
-
- /* If zero, or denormal, or exponent underflows too much for a denormal
- * half, return signed zero. */
- if (e < 103)
- return bits;
-
- /* If NaN, return NaN. If Inf or exponent overflow, return Inf. */
- if (e > 142) {
- bits |= 0x7c00u;
- /* If exponent was 0xff and one mantissa bit was set, it means NaN,
- * not Inf, so make sure we set one mantissa bit too. */
- bits |= e == 255 && (x & 0x007fffffu);
- return bits;
- }
-
- /* If exponent underflows but not too much, return a denormal */
- if (e < 113) {
- m |= 0x0800u;
- /* Extra rounding may overflow and set mantissa to 0 and exponent
- * to 1, which is OK. */
- bits |= (m >> (114 - e)) + ((m >> (113 - e)) & 1);
- return bits;
- }
-
- bits |= ((e - 112) << 10) | (m >> 1);
- /* Extra rounding. An overflow will set mantissa to 0 and increment
- * the exponent, which is OK. */
- bits += m & 1;
- return bits;
-}
-
-static int check_half_device(void)
-{
- std::string extStr;
- size_t param_value_size;
- OCL_CALL(clGetDeviceInfo, device, CL_DEVICE_EXTENSIONS, 0, 0, ¶m_value_size);
- std::vector<char> param_value(param_value_size);
- OCL_CALL(clGetDeviceInfo, device, CL_DEVICE_EXTENSIONS, param_value_size,
- param_value.empty() ? NULL : ¶m_value.front(), ¶m_value_size);
- if (!param_value.empty())
- extStr = std::string(¶m_value.front(), param_value_size-1);
-
- if (std::strstr(extStr.c_str(), "cl_khr_fp16") == NULL) {
- printf("No cl_khr_fp16, Skip!");
- return 0;
- }
-
- return 1;
-}
-
void compiler_half_basic(void)
{
const size_t n = 16;
@@ -131,7 +12,7 @@ void compiler_half_basic(void)
float f = 2.5;
uint32_t tmp_f;
- if (!check_half_device())
+ if (!cl_check_half())
return;
memcpy(&tmp_f, &f, sizeof(float));
@@ -197,7 +78,7 @@ static float half_test_src[half_n] = {
uint32_t tmp_f; \
float f; \
\
- if (!check_half_device()) \
+ if (!cl_check_half()) \
return; \
\
OCL_CREATE_KERNEL_FROM_FILE("compiler_half_math", "compiler_half_math_" #NAME); \
@@ -263,7 +144,7 @@ HALF_MATH_TEST_1ARG(ceil, ceilf);
uint32_t tmp_f; \
float f; \
\
- if (!check_half_device()) \
+ if (!cl_check_half()) \
return; \
\
OCL_CREATE_KERNEL_FROM_FILE("compiler_half_math", "compiler_half_math_" #NAME); \
@@ -325,7 +206,7 @@ void compiler_half_isnan(void)
const size_t n = 16*2;
uint16_t hsrc[n];
- if (!check_half_device())
+ if (!cl_check_half())
return;
// Setup kernel and buffers
@@ -366,7 +247,7 @@ void compiler_half_isinf(void)
const size_t n = 16;
uint16_t hsrc[n];
- if (!check_half_device())
+ if (!cl_check_half())
return;
// Setup kernel and buffers
@@ -413,7 +294,7 @@ void compiler_half_to_float(void)
float fdst[n];
uint32_t tmp_f;
- if (!check_half_device())
+ if (!cl_check_half())
return;
// Setup kernel and buffers
@@ -458,7 +339,7 @@ void compiler_half_as_char2(void)
uint16_t hsrc[n];
uint8_t* csrc = (uint8_t*)hsrc;
- if (!check_half_device())
+ if (!cl_check_half())
return;
// Setup kernel and buffers
@@ -500,7 +381,7 @@ void compiler_half2_as_int(void)
uint16_t hsrc[n];
int* isrc = (int*)hsrc;
- if (!check_half_device())
+ if (!cl_check_half())
return;
// Setup kernel and buffers
@@ -544,7 +425,7 @@ void compiler_half_to_char_sat(void)
char dst[n];
uint32_t tmp_f;
- if (!check_half_device())
+ if (!cl_check_half())
return;
// Setup kernel and buffers
@@ -597,7 +478,7 @@ void compiler_half_to_ushort_sat(void)
uint16_t dst[n];
uint32_t tmp_f;
- if (!check_half_device())
+ if (!cl_check_half())
return;
// Setup kernel and buffers
@@ -648,7 +529,7 @@ void compiler_half_to_uint_sat(void)
uint32_t dst[n];
uint32_t tmp_f;
- if (!check_half_device())
+ if (!cl_check_half())
return;
// Setup kernel and buffers
@@ -698,7 +579,7 @@ void compiler_uchar_to_half(void)
float fdst[n];
uint32_t tmp_f;
- if (!check_half_device())
+ if (!cl_check_half())
return;
// Setup kernel and buffers
@@ -745,7 +626,7 @@ void compiler_int_to_half(void)
float fdst[n];
uint32_t tmp_f;
- if (!check_half_device())
+ if (!cl_check_half())
return;
// Setup kernel and buffers
@@ -793,7 +674,7 @@ void compiler_half_to_long(void)
uint32_t tmp_f;
float f;
- if (!check_half_device())
+ if (!cl_check_half())
return;
// Setup kernel and buffers
@@ -840,7 +721,7 @@ void compiler_ulong_to_half(void)
uint32_t tmp_f;
float f;
- if (!check_half_device())
+ if (!cl_check_half())
return;
// Setup kernel and buffers
@@ -887,7 +768,7 @@ void compiler_half_to_long_sat(void)
uint32_t tmp_f;
float f;
- if (!check_half_device())
+ if (!cl_check_half())
return;
// Setup kernel and buffers
@@ -938,7 +819,7 @@ void compiler_half_to_double(void)
uint32_t tmp_f;
float f;
-// if (!check_half_device())
+// if (!cl_check_half())
// return;
if (!cl_check_double())
return;
@@ -988,7 +869,7 @@ void compiler_double_to_half(void)
uint32_t tmp_f;
float f;
-// if (!check_half_device())
+// if (!cl_check_half())
// return;
if (!cl_check_double())
return;
diff --git a/utests/utest_helper.cpp b/utests/utest_helper.cpp
index 3388d9f..5a2ac6e 100644
--- a/utests/utest_helper.cpp
+++ b/utests/utest_helper.cpp
@@ -28,6 +28,7 @@
#include <cstring>
#include <cassert>
#include <cmath>
+#include <algorithm>
#define FATAL(...) \
do { \
@@ -927,3 +928,121 @@ int cl_check_ocl20(void)
free(device_version_str);
return 1;
}
+
+int cl_check_half(void)
+{
+ std::string extStr;
+ size_t param_value_size;
+ OCL_CALL(clGetDeviceInfo, device, CL_DEVICE_EXTENSIONS, 0, 0, ¶m_value_size);
+ std::vector<char> param_value(param_value_size);
+ OCL_CALL(clGetDeviceInfo, device, CL_DEVICE_EXTENSIONS, param_value_size,
+ param_value.empty() ? NULL : ¶m_value.front(), ¶m_value_size);
+ if (!param_value.empty())
+ extStr = std::string(¶m_value.front(), param_value_size-1);
+
+ if (std::strstr(extStr.c_str(), "cl_khr_fp16") == NULL) {
+ printf("No cl_khr_fp16, Skip!");
+ return 0;
+ }
+
+ return 1;
+}
+
+uint32_t __half_to_float(uint16_t h, bool* isInf, bool* infSign)
+{
+ struct __FP32 {
+ uint32_t mantissa:23;
+ uint32_t exponent:8;
+ uint32_t sign:1;
+ };
+ struct __FP16 {
+ uint32_t mantissa:10;
+ uint32_t exponent:5;
+ uint32_t sign:1;
+ };
+ uint32_t f;
+ __FP32 o;
+ memset(&o, 0, sizeof(o));
+ __FP16 i;
+ memcpy(&i, &h, sizeof(uint16_t));
+
+ if (isInf)
+ *isInf = false;
+ if (infSign)
+ *infSign = false;
+
+ if (i.exponent == 0 && i.mantissa == 0) // (Signed) zero
+ o.sign = i.sign;
+ else {
+ if (i.exponent == 0) { // Denormal (converts to normalized)
+ // Adjust mantissa so it's normalized (and keep
+ // track of exponent adjustment)
+ int e = -1;
+ uint m = i.mantissa;
+ do {
+ e++;
+ m <<= 1;
+ } while ((m & 0x400) == 0);
+
+ o.mantissa = (m & 0x3ff) << 13;
+ o.exponent = 127 - 15 - e;
+ o.sign = i.sign;
+ } else if (i.exponent == 0x1f) { // Inf/NaN
+ // NOTE: Both can be handled with same code path
+ // since we just pass through mantissa bits.
+ o.mantissa = i.mantissa << 13;
+ o.exponent = 255;
+ o.sign = i.sign;
+
+ if (isInf) {
+ *isInf = (i.mantissa == 0);
+ if (infSign)
+ *infSign = !i.sign;
+ }
+ } else { // Normalized number
+ o.mantissa = i.mantissa << 13;
+ o.exponent = 127 - 15 + i.exponent;
+ o.sign = i.sign;
+ }
+ }
+
+ memcpy(&f, &o, sizeof(uint32_t));
+ return f;
+}
+
+
+uint16_t __float_to_half(uint32_t x)
+{
+ uint16_t bits = (x >> 16) & 0x8000; /* Get the sign */
+ uint16_t m = (x >> 12) & 0x07ff; /* Keep one extra bit for rounding */
+ unsigned int e = (x >> 23) & 0xff; /* Using int is faster here */
+
+ /* If zero, or denormal, or exponent underflows too much for a denormal
+ * half, return signed zero. */
+ if (e < 103)
+ return bits;
+
+ /* If NaN, return NaN. If Inf or exponent overflow, return Inf. */
+ if (e > 142) {
+ bits |= 0x7c00u;
+ /* If exponent was 0xff and one mantissa bit was set, it means NaN,
+ * not Inf, so make sure we set one mantissa bit too. */
+ bits |= e == 255 && (x & 0x007fffffu);
+ return bits;
+ }
+
+ /* If exponent underflows but not too much, return a denormal */
+ if (e < 113) {
+ m |= 0x0800u;
+ /* Extra rounding may overflow and set mantissa to 0 and exponent
+ * to 1, which is OK. */
+ bits |= (m >> (114 - e)) + ((m >> (113 - e)) & 1);
+ return bits;
+ }
+
+ bits |= ((e - 112) << 10) | (m >> 1);
+ /* Extra rounding. An overflow will set mantissa to 0 and increment
+ * the exponent, which is OK. */
+ bits += m & 1;
+ return bits;
+}
diff --git a/utests/utest_helper.hpp b/utests/utest_helper.hpp
index 421e356..561c2c4 100644
--- a/utests/utest_helper.hpp
+++ b/utests/utest_helper.hpp
@@ -299,4 +299,11 @@ extern clGetKernelSubGroupInfoKHR_cb* utestclGetKernelSubGroupInfoKHR;
/* Check is cl version 2.0. */
extern int cl_check_ocl20(void);
+
+/* Check is FP16 enabled. */
+extern int cl_check_half(void);
+
+/* Helper function for half type numbers */
+extern uint32_t __half_to_float(uint16_t h, bool* isInf = NULL, bool* infSign = NULL);
+extern uint16_t __float_to_half(uint32_t x);
#endif /* __UTEST_HELPER_HPP__ */
--
2.7.4
More information about the Beignet
mailing list