From b92605df1f528ec1601f3a5f8311328afa61cd6a Mon Sep 17 00:00:00 2001 From: Christophe Murphy Date: Mon, 3 Jun 2024 16:56:57 -0700 Subject: [PATCH 1/3] Add cases for float16 arguments to atan2 and hypot functions --- src/api/c/binary.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/api/c/binary.cpp b/src/api/c/binary.cpp index 50590568f8..ee727c264a 100644 --- a/src/api/c/binary.cpp +++ b/src/api/c/binary.cpp @@ -476,7 +476,7 @@ af_err af_atan2(af_array *out, const af_array lhs, const af_array rhs, try { const af_dtype type = implicit(lhs, rhs); - if (type != f32 && type != f64) { + if (type != f16 && type != f32 && type != f64) { AF_ERROR("Only floating point arrays are supported for atan2 ", AF_ERR_NOT_SUPPORTED); } @@ -491,6 +491,7 @@ af_err af_atan2(af_array *out, const af_array lhs, const af_array rhs, af_array res; switch (type) { + case f16: res = arithOp(lhs, rhs, odims); break; case f32: res = arithOp(lhs, rhs, odims); break; case f64: res = arithOp(lhs, rhs, odims); break; default: TYPE_ERROR(0, type); @@ -507,7 +508,7 @@ af_err af_hypot(af_array *out, const af_array lhs, const af_array rhs, try { const af_dtype type = implicit(lhs, rhs); - if (type != f32 && type != f64) { + if (type != f16 && type != f32 && type != f64) { AF_ERROR("Only floating point arrays are supported for hypot ", AF_ERR_NOT_SUPPORTED); } @@ -523,6 +524,7 @@ af_err af_hypot(af_array *out, const af_array lhs, const af_array rhs, af_array res; switch (type) { + case f16: res = arithOp(lhs, rhs, odims); break; case f32: res = arithOp(lhs, rhs, odims); break; case f64: res = arithOp(lhs, rhs, odims); break; default: TYPE_ERROR(0, type); From 5e1e3362adee86572b2a05209b6b2780daef71c1 Mon Sep 17 00:00:00 2001 From: Christophe Murphy Date: Wed, 5 Jun 2024 12:38:57 -0700 Subject: [PATCH 2/3] Added test cases for half precision atan2 and hypot functions --- test/binary.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/binary.cpp b/test/binary.cpp index dafc3b8bff..c029a19da5 100644 --- a/test/binary.cpp +++ b/test/binary.cpp @@ -14,6 +14,8 @@ #include #include #include +#include +#include "half.hpp" //note: NOT common. From extern/half/include/half.hpp #include #include @@ -21,6 +23,8 @@ using namespace std; using namespace af; +using half_float_half = half_float::half; + const int num = 10000; #define add(left, right) (left) + (right) @@ -122,7 +126,7 @@ af::array randgen(const int num, dtype ty) { \ af_dtype ta = (af_dtype)dtype_traits::af_type; \ af::array a = randgen(num, ta); \ - Tb h_b = 0.3; \ + Tb h_b = (Tb)0.3; \ af::array c = func(a, h_b); \ Ta *h_a = a.host(); \ Td *h_d = c.host(); \ @@ -139,7 +143,7 @@ af::array randgen(const int num, dtype ty) { SUPPORTED_TYPE_CHECK(Tc); \ \ af_dtype tb = (af_dtype)dtype_traits::af_type; \ - Ta h_a = 0.3; \ + Ta h_a = (Ta)0.3; \ af::array b = randgen(num, tb); \ af::array c = func(h_a, b); \ Tb *h_b = b.host(); \ @@ -163,6 +167,8 @@ af::array randgen(const int num, dtype ty) { #define BINARY_TESTS_UINT(func) BINARY_TESTS(uint, uint, uint, func) #define BINARY_TESTS_INTL(func) BINARY_TESTS(intl, intl, intl, func) #define BINARY_TESTS_UINTL(func) BINARY_TESTS(uintl, uintl, uintl, func) +#define BINARY_TESTS_NEAR_HALF(func) \ + BINARY_TESTS_NEAR(half_float_half, half_float_half, half_float_half, func, 1e-3) #define BINARY_TESTS_NEAR_FLOAT(func) \ BINARY_TESTS_NEAR(float, float, float, func, 1e-5) #define BINARY_TESTS_NEAR_DOUBLE(func) \ @@ -188,6 +194,9 @@ BINARY_TESTS_NEAR_FLOAT(atan2) BINARY_TESTS_NEAR_FLOAT(pow) BINARY_TESTS_NEAR_FLOAT(hypot) +BINARY_TESTS_NEAR_HALF(atan2) +BINARY_TESTS_NEAR_HALF(hypot) + BINARY_TESTS_NEAR_DOUBLE(atan2) BINARY_TESTS_NEAR_DOUBLE(pow) BINARY_TESTS_NEAR_DOUBLE(hypot) From abd46ee932cc3ef26dd4afaae19d82dab85be202 Mon Sep 17 00:00:00 2001 From: Christophe Murphy Date: Thu, 6 Jun 2024 12:54:30 -0700 Subject: [PATCH 3/3] Fix for incorrect result when using the pow function with float16 arguments with the CUDA backend. Since the half precision CUDA library doesn't have a pow function, the default pow function is used, casting the arguments to double precision. --- src/backend/cuda/kernel/jit.cuh | 5 ----- test/binary.cpp | 1 + 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/backend/cuda/kernel/jit.cuh b/src/backend/cuda/kernel/jit.cuh index cfb5837719..76fd344010 100644 --- a/src/backend/cuda/kernel/jit.cuh +++ b/src/backend/cuda/kernel/jit.cuh @@ -59,14 +59,9 @@ typedef cuDoubleComplex cdouble; #define __rem(lhs, rhs) ((lhs) % (rhs)) #define __mod(lhs, rhs) ((lhs) % (rhs)) -#ifdef AF_WITH_FAST_MATH #define __pow(lhs, rhs) \ static_cast( \ pow(static_cast(lhs), static_cast(rhs))); -#else -#define __pow(lhs, rhs) \ - __float2int_rn(powf(__int2float_rn((int)lhs), __int2float_rn((int)rhs))) -#endif #define __powll(lhs, rhs) \ __double2ll_rn(pow(__ll2double_rn(lhs), __ll2double_rn(rhs))) #define __powul(lhs, rhs) \ diff --git a/test/binary.cpp b/test/binary.cpp index c029a19da5..a274c11346 100644 --- a/test/binary.cpp +++ b/test/binary.cpp @@ -195,6 +195,7 @@ BINARY_TESTS_NEAR_FLOAT(pow) BINARY_TESTS_NEAR_FLOAT(hypot) BINARY_TESTS_NEAR_HALF(atan2) +BINARY_TESTS_NEAR_HALF(pow) BINARY_TESTS_NEAR_HALF(hypot) BINARY_TESTS_NEAR_DOUBLE(atan2)