From 150b39e35c3f5b3bb07ab7a542eeed7ebeff57df Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Thu, 18 Aug 2016 12:56:37 +0800 Subject: Utest: Add test for half type subgroup functions Check if device support subgroup and half first, use build options to hide code for unsported device. V2: Fix half part test case for utest multithread. Signed-off-by: Pan Xiuli Reviewed-by: Yang Rong --- utests/compiler_subgroup_scan_inclusive.cpp | 100 ++++++++++++++++++++++++---- 1 file changed, 87 insertions(+), 13 deletions(-) (limited to 'utests/compiler_subgroup_scan_inclusive.cpp') diff --git a/utests/compiler_subgroup_scan_inclusive.cpp b/utests/compiler_subgroup_scan_inclusive.cpp index fa328552..0f0df1c8 100644 --- a/utests/compiler_subgroup_scan_inclusive.cpp +++ b/utests/compiler_subgroup_scan_inclusive.cpp @@ -32,25 +32,41 @@ template static void compute_expected(WG_FUNCTION wg_func, T* input, T* expected, - size_t SIMD_SIZE) + size_t SIMD_SIZE, + bool IS_HALF) { if(wg_func == WG_SCAN_INCLUSIVE_ADD) { expected[0] = input[0]; - for(uint32_t i = 1; i < SIMD_SIZE; i++) - expected[i] = input[i] + expected[i - 1]; + for(uint32_t i = 1; i < SIMD_SIZE; i++) { + if (IS_HALF) + expected[i] = __float_to_half(as_uint(as_float(__half_to_float(input[i])) + + as_float(__half_to_float(expected[i - 1])))); + else + expected[i] = input[i] + expected[i - 1]; + } } else if(wg_func == WG_SCAN_INCLUSIVE_MAX) { expected[0] = input[0]; - for(uint32_t i = 1; i < SIMD_SIZE; i++) - expected[i] = max(input[i], expected[i - 1]); + for(uint32_t i = 1; i < SIMD_SIZE; i++) { + if (IS_HALF) + expected[i] = (as_float(__half_to_float(input[i])) > as_float(__half_to_float(expected[i - 1]))) ? + input[i] : expected[i - 1]; + else + expected[i] = max(input[i], expected[i - 1]); + } } else if(wg_func == WG_SCAN_INCLUSIVE_MIN) { expected[0] = input[0]; - for(uint32_t i = 1; i < SIMD_SIZE; i++) - expected[i] = min(input[i], expected[i - 1]); + for(uint32_t i = 1; i < SIMD_SIZE; i++) { + if (IS_HALF) + expected[i] = (as_float(__half_to_float(input[i])) < as_float(__half_to_float(expected[i - 1]))) ? + input[i] : expected[i - 1]; + else + expected[i] = min(input[i], expected[i - 1]); + } } } @@ -62,7 +78,8 @@ template static void generate_data(WG_FUNCTION wg_func, T* &input, T* &expected, - size_t SIMD_SIZE) + size_t SIMD_SIZE, + bool IS_HALF) { input = new T[WG_GLOBAL_SIZE]; expected = new T[WG_GLOBAL_SIZE]; @@ -91,6 +108,8 @@ static void generate_data(WG_FUNCTION wg_func, input[gid + lid] += ((rand() % 2 - 1) * base_val); /* add trailing random bits, tests GENERAL cases */ input[gid + lid] += (rand() % 112); + if (IS_HALF) + input[gid + lid] = __float_to_half(as_uint((float)input[gid + lid]/2)); #if DEBUG_STDOUT /* output generated input */ @@ -101,7 +120,7 @@ static void generate_data(WG_FUNCTION wg_func, } /* expected values */ - compute_expected(wg_func, input + gid, expected + gid, SIMD_SIZE); + compute_expected(wg_func, input + gid, expected + gid, SIMD_SIZE, IS_HALF); #if DEBUG_STDOUT /* output expected input */ @@ -124,7 +143,8 @@ static void generate_data(WG_FUNCTION wg_func, template static void subgroup_generic(WG_FUNCTION wg_func, T* input, - T* expected) + T* expected, + bool IS_HALF = false) { /* get simd size */ globals[0] = WG_GLOBAL_SIZE; @@ -133,7 +153,7 @@ static void subgroup_generic(WG_FUNCTION wg_func, OCL_CALL(utestclGetKernelSubGroupInfoKHR,kernel,device,CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE_KHR,sizeof(size_t)*1,locals,sizeof(size_t),&SIMD_SIZE,NULL); /* input and expected data */ - generate_data(wg_func, input, expected, SIMD_SIZE); + generate_data(wg_func, input, expected, SIMD_SIZE, IS_HALF); /* prepare input for data type */ OCL_CREATE_BUFFER(buf[0], 0, WG_GLOBAL_SIZE * sizeof(T), NULL); @@ -156,8 +176,21 @@ static void subgroup_generic(WG_FUNCTION wg_func, for (uint32_t i = 0; i < WG_GLOBAL_SIZE; i++) if(((T *)buf_data[1])[i] != *(expected + i)) { + if (IS_HALF) { + float num_computed = as_float(__half_to_float(((T *)buf_data[1])[i])); + float num_expected = as_float(__half_to_float(*(expected + i))); + float num_diff = abs(num_computed - num_expected) / abs(num_expected); + if (num_diff > 0.03f) { + mismatches++; +#if DEBUG_STDOUT + /* output mismatch */ + cout << "Err at " << i << ", " << num_computed + << " != " << num_expected <<" diff: " <::is_integer){ + else if (numeric_limits::is_integer) { mismatches++; #if DEBUG_STDOUT @@ -251,6 +284,20 @@ void compiler_subgroup_scan_inclusive_add_float(void) subgroup_generic(WG_SCAN_INCLUSIVE_ADD, input, expected); } MAKE_UTEST_FROM_FUNCTION(compiler_subgroup_scan_inclusive_add_float); +void compiler_subgroup_scan_inclusive_add_half(void) +{ + if(!cl_check_subgroups()) + return; + if(!cl_check_half()) + return; + cl_half *input = NULL; + cl_half *expected = NULL; + OCL_CALL(cl_kernel_init, "compiler_subgroup_scan_inclusive.cl", + "compiler_subgroup_scan_inclusive_add_half", + SOURCE, "-DHALF"); + subgroup_generic(WG_SCAN_INCLUSIVE_ADD, input, expected, true); +} +MAKE_UTEST_FROM_FUNCTION(compiler_subgroup_scan_inclusive_add_half); /* * Workgroup scan_inclusive max utest functions @@ -310,6 +357,20 @@ void compiler_subgroup_scan_inclusive_max_float(void) subgroup_generic(WG_SCAN_INCLUSIVE_MAX, input, expected); } MAKE_UTEST_FROM_FUNCTION(compiler_subgroup_scan_inclusive_max_float); +void compiler_subgroup_scan_inclusive_max_half(void) +{ + if(!cl_check_subgroups()) + return; + if(!cl_check_half()) + return; + cl_half *input = NULL; + cl_half *expected = NULL; + OCL_CALL(cl_kernel_init, "compiler_subgroup_scan_inclusive.cl", + "compiler_subgroup_scan_inclusive_max_half", + SOURCE, "-DHALF"); + subgroup_generic(WG_SCAN_INCLUSIVE_MAX, input, expected, true); +} +MAKE_UTEST_FROM_FUNCTION(compiler_subgroup_scan_inclusive_max_half); /* * Workgroup scan_inclusive min utest functions @@ -369,4 +430,17 @@ void compiler_subgroup_scan_inclusive_min_float(void) subgroup_generic(WG_SCAN_INCLUSIVE_MIN, input, expected); } MAKE_UTEST_FROM_FUNCTION(compiler_subgroup_scan_inclusive_min_float); - +void compiler_subgroup_scan_inclusive_min_half(void) +{ + if(!cl_check_subgroups()) + return; + if(!cl_check_half()) + return; + cl_half *input = NULL; + cl_half *expected = NULL; + OCL_CALL(cl_kernel_init, "compiler_subgroup_scan_inclusive.cl", + "compiler_subgroup_scan_inclusive_min_half", + SOURCE, "-DHALF"); + subgroup_generic(WG_SCAN_INCLUSIVE_MIN, input, expected, true); +} +MAKE_UTEST_FROM_FUNCTION(compiler_subgroup_scan_inclusive_min_half); -- cgit v1.2.1