implement conversion between half and single precision for denormals#1927
implement conversion between half and single precision for denormals#1927
Conversation
yhmtsai
left a comment
There was a problem hiding this comment.
Nice work!
I will suggest you put comments to describe leading_zeros, new_exponent, new_significand operation.
include/ginkgo/core/base/half.hpp
Outdated
| } | ||
|
|
||
| auto leading_zeros = | ||
| __builtin_clz(f16_traits::significand_mask & data_) - |
There was a problem hiding this comment.
| __builtin_clz(f16_traits::significand_mask & data_) - | |
| __builtin_clz(static_cast<std::uint32_t>(f16_traits::significand_mask & data_)) - |
Because __builtin_clz only support unsigned integer, making it more explicitly will help understanding.
There was a problem hiding this comment.
Additionally you will need to create a clz function in detail namespace to make it also support MSVC platform.
Check bitscanreverse and core/base/intrinsics.hpp
https://learn.microsoft.com/en-us/cpp/intrinsics/bitscanreverse-bitscanreverse64?view=msvc-170
| auto new_exponent = | ||
| ((conv::bias_change >> f32_traits::significand_bits) - | ||
| leading_zeros) | ||
| << f32_traits::significand_bits; |
There was a problem hiding this comment.
| auto new_exponent = | |
| ((conv::bias_change >> f32_traits::significand_bits) - | |
| leading_zeros) | |
| << f32_traits::significand_bits; | |
| auto new_exponent = | |
| conv::bias_change - (leading_zeros << f32_traits::significand_bits); |
It also worth noting leading_zeros is alway less than bias change because we are at half -> float
yhmtsai
left a comment
There was a problem hiding this comment.
LGTM!
some improvement and the test suggestion
include/ginkgo/core/base/half.hpp
Outdated
| f16_traits::significand_bits) + | ||
| f32_traits::significand_bits - | ||
| f16_traits::significand_bits + 1; | ||
| if (tail_length > f32_traits::significand_bits + 1) { |
There was a problem hiding this comment.
| if (tail_length > f32_traits::significand_bits + 1) { | |
| // all significant (including implicitly leading 1) will be moved after representation field more than one digit (less than half) such that it will rounding to zero. | |
| if (tail_length > f32_traits::significand_bits + 1) { |
please feel free to rephrase the sentence
yhmtsai
left a comment
There was a problem hiding this comment.
LGTM. some corner test are required
include/ginkgo/core/base/half.hpp
Outdated
| (conv::bias_change - ((data_ & f32_traits::exponent_mask) >> | ||
| conv::significand_offset) >> | ||
| f16_traits::significand_bits) + |
There was a problem hiding this comment.
| (conv::bias_change - ((data_ & f32_traits::exponent_mask) >> | |
| conv::significand_offset) >> | |
| f16_traits::significand_bits) + | |
| ((conv::bias_change - ((data_ & f32_traits::exponent_mask) >> | |
| conv::significand_offset)) >> | |
| f16_traits::significand_bits) + |
to ensure the ordering and avoid warning
include/ginkgo/core/base/half.hpp
Outdated
| __builtin_clz(static_cast<std::uint32_t>( | ||
| f16_traits::significand_mask & data_)) - | ||
| f16_traits::exponent_bits - f16_traits::sign_bits - | ||
| 8 * (sizeof(conv::result_bits) - sizeof(conv::source_bits)); |
There was a problem hiding this comment.
| 8 * (sizeof(conv::result_bits) - sizeof(conv::source_bits)); | |
| CHAR_BIT * (sizeof(conv::result_bits) - sizeof(conv::source_bits)); |
this is predefined macro from climits
| } | ||
|
|
||
|
|
||
| TEST(FloatToHalf, RoundsUpToEvenNumber) |
There was a problem hiding this comment.
maybe add another test from rounds down to even number by adding one last bit into the end to ensure we compare full tail before shift.
|
Hi @emre-safa , do you have some time to work on this? |
I thought this job was done, I will have a look at it as soon as I have time. Sorry for late reply. |
|
Error: The following files need to be formatted: You can find a formatting patch under Artifacts here or run |
conversion from single to half will be provided