【问题标题】:Cheap approximate integer division on a GPUGPU 上廉价的近似整数除法
【发布时间】:2017-07-20 23:48:29
【问题描述】:

所以,我想在 GPU 上除以一些 32 位无符号整数,我不关心得到一个精确的结果。事实上,让我们宽容一点,假设我愿意接受高达 2 的乘法误差因子,即如果 q = x/y 我愿意接受介于 0.5*q 和 2*q 之间的任何值。

我还没有测量任何东西,但在我看来,这样的东西(CUDA 代码)应该很有用:

__device__ unsigned cheap_approximate_division(unsigned dividend, unsigned divisor)
{
    return 1u << (__clz(dividend) - __clz(divisor));
}

它使用 "find first (bit) set" integer intrinsic 作为廉价的以 2 为底的对数函数。

注意:我可以使这个非 32 位特定,但我必须使用模板使代码复杂化,用模板函数包装 __clz() 以使用 __clzl()__clzll()

问题:

  • 就时钟周期而言,这种近似除法是否有更好的方法?也许有稍微不同的约束?
  • 如果我想要更高的精度,我应该使用整数还是只使用浮点算术?

【问题讨论】:

    标签: cuda integer-division approximate


    【解决方案1】:

    通过浮点运算可以得到更精确的结果,在大多数架构上指令数略低,并且可能会提高吞吐量:

    __device__ unsigned cheap_approximate_division(unsigned dividend, unsigned divisor)
    {
       return (unsigned)(__fdividef(dividend, divisor) /*+0.5f*/ );
    }
    

    注释中的+0.5f 应表明您还可以将float->int 转换为适当的舍入,除了更高的能耗(它将fmul 转换为fmad 与常数直接来自常量缓存)。不过,四舍五入会使您远离确切的整数结果。

    【讨论】:

    • 你能在这里抛出一些周期计数吗?假设我使用的所有整数运算是每个扭曲 1 个周期,并且所有内容都在寄存器中,那么我应该只使用 4;这个版本是多少个周期?
    • 抱歉,您必须对自己的 atm 进行基准测试。但是请记住__ffs() compiles to a multiple instruction emulation sequence on newer architectures。您是否针对特定架构?
    • @einpoklum 如果您迁移到 GCN 的 opencl,它也会在后端模拟整数除法 fp。 Fp 必须是最快的选项。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-25
    • 2016-02-07
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    • 2018-01-10
    • 1970-01-01
    相关资源
    最近更新 更多