You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用AVX2高效实现Int128与Double转换及宽范围位置表示

问题背景

我正在开发一款支持用户在超大空间范围(直径至少100万光年)内移动的软件,要求位置表示精度不低于0.1毫米,计划采用128位定点数(fixed128)存储位置。但距离、开方、除法、积分等数学运算更适合用双精度(double)或单精度浮点数处理——通常是对两个int128坐标相减得到相对距离,此时差值足够小不会损失过多精度;而差值大的场景对精度要求也较低。

在实现fixed128时,我遇到了核心问题:如何利用AVX2 SIMD指令集快速实现int128与double的双向转换?(AVX512普及度不足,无法在该软件中使用)

已尝试方案

我参考过关于SSE/AVX下高效实现double/int64转换的方案,其中Wim的思路是将int64拆分为小于52位的尾数部分,拼接指数位后通过浮点运算还原成double,这种方式效率较高。

基于此思路,我尝试将由两个uint64(ilow和ihigh)组成的uint128拆分为三部分:

  • v_lo:ilow的低48位;
  • v_mi:ilow的高16位 + ihigh的低16位;
  • v_hi:ihigh的高48位;

v_lo和v_hi的转换可以参考Wim的uint64_to_double_fast_precise方法,但v_mi的转换需要4条指令,比v_lo和v_hi的指令数之和(1+2)还多。我怀疑可以通过permute/shuffle/unpack等混洗指令组合实现更高效的转换,但对这类指令的使用不太熟悉。

现有ufixed128转double代码

constexpr auto fix128_frac_bits = 32;

__m256d ufixed128_to_double_fast(const __m256i& ihigh, const __m256i& ilow)
{
//constants
__m256d magic_d_hm = _mm256_set1_pd(pow(2.0, 52 + 48 - fix128_frac_bits) + pow(2.0, 52 + 80 - fix128_frac_bits));
__m256d magic_d_lo = _mm256_set1_pd(pow(2.0, 52 - fix128_frac_bits));
__m256i magic_i_lo = _mm256_castpd_si256(magic_d_lo);
__m256i magic_i_mi = _mm256_castpd_si256(_mm256_set1_pd(pow(2.0, 52 + 48 - fix128_frac_bits)));
__m256i magic_i_hi = _mm256_castpd_si256(_mm256_set1_pd(pow(2.0, 52 + 80 - fix128_frac_bits)));
//majik operations
__m256i v_lo = _mm256_blend_epi16(ilow, magic_i_lo, 0b10001000);
__m256i v_mi = _mm256_slli_epi64(ihigh, 16);
__m256i losr48 = _mm256_srli_epi64(ilow, 48);
v_mi = _mm256_xor_si256(v_mi, losr48);
v_mi = _mm256_blend_epi32(magic_i_mi, v_mi, 0b01010101);
__m256i v_hi = _mm256_srli_epi64(ihigh, 16);
v_hi = _mm256_xor_si256(v_hi, magic_i_hi);
//final fp 
__m256d loresult = _mm256_sub_pd(_mm256_castsi256_pd(v_lo), magic_d_lo);
__m256d result = _mm256_sub_pd(_mm256_castsi256_pd(v_hi), magic_d_hm);
result = _mm256_add_pd(result, _mm256_castsi256_pd(v_mi));
result = _mm256_add_pd(result, loresult);
return result;
}

补充说明

我已实现有符号fixed128转double的功能,只需在magic_d_hm和magic_i_hi中加入2.0^(127 - fix128_frac_bits)即可。但目前还没有高效的double转int128/uint128实现——我能通过位运算实现比C++ static_cast更快的标量转换,但远不如上述转换高效,且需要占用大量寄存器存储常量。

需求帮助

  • 优化AVX2下int128与double的双向转换效率;
  • 若当前方案不可行,提供替代的宽范围高精度位置表示方案(排除浮点原点/浮点网格方案,因其物理计算不稳定、上层实现复杂或难以AVX加速)。

注:我计划在完成fixed128和double-double的高度优化后对比性能,再决定使用哪种方案。当前代码托管于个人代码仓库。

内容的提问来源于stack exchange,提问作者Velctor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 01:33:24