Skip to content

fix: Refactor IndexingBackwardKernel to accelerate#1

Closed
hushenwei2000 wants to merge 1 commit intodevelopfrom
fix_indexingbackwardkernel
Closed

fix: Refactor IndexingBackwardKernel to accelerate#1
hushenwei2000 wants to merge 1 commit intodevelopfrom
fix_indexingbackwardkernel

Conversation

@hushenwei2000
Copy link
Owner

PR Category

Operator Mechanism

PR Types

Improvements

Description

perf(gpu): 优化索引反向核的累加逻辑以减少全局内存访问

  • accumulate 参数从函数参数移至模板参数,允许编译器优化
  • 针对累加模式,先在寄存器中累加同一组的梯度,再一次性写入全局内存
  • 避免了对同一地址的重复读-改-写操作,减少内存延迟影响
  • 针对非累加模式,直接定位重复组的最后一个索引进行赋值

旧代码(N 个重复 index,对同一个 feature 元素):

// 每次迭代都经过 scalar_t 精度截断
for each duplicate i:
    weight = (opmath_t) grad_weight[addr]   // 读回 scalar_t → 提升精度
    weight += (opmath_t) grad_output[row_i]  // opmath_t 精度加法
    grad_weight[addr] = (scalar_t) weight    // ← 截断回 scalar_t

新代码:

// 全程在 opmath_t 精度中累加,最后只截断一次
acc = 0                                       // opmath_t
for each duplicate i:
    acc += (opmath_t) grad_output[row_i]      // opmath_t 精度累加

grad_weight[addr] = (scalar_t)((opmath_t)grad_weight[addr] + acc)  // ← 只截断一次

按类型分析:

类型 opmath_t 是否 bit-identical 精度变化
float float 无差异
double double 无差异
int / int64_t 自身 无差异
float16 float 精度更高
bfloat16 float 精度更高

结论:

旧代码每次迭代将中间和截断回 float16(10 bit 尾数),N 次累加产生 N 次舍入误差:

step1: fp32 sum → 截断为 fp16 → 写回
step2: 读回 fp16 → 提升为 fp32 → 加法 → 截断为 fp16 → 写回  (丢失精度)
step3: 同上...

新代码全程在 float32(23 bit 尾数)中累加,只在最终写回时截断一次为 float16。

新代码的精度严格 >= 旧代码。对 float/double/int 类型结果完全一致;对 float16/bfloat16 类型精度更好(减少了中间舍入误差)。不存在精度下降的风险。

是否引起精度变化

@hushenwei2000
Copy link
Owner Author

/re-run all-failed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant