059、NPU的GELU与Swish激活函数:硬件友好性分析
NPU的GELU与Swish激活函数:硬件友好性分析去年做一款AIoT芯片的NPU验证时,遇到一个诡异的精度问题。模型在GPU上跑得好好的,量化后部署到NPU上,分类准确率直接掉了3个点。排查了三天,最后定位到是激活函数实现的问题——软件仿真库里的GELU用了近似公式,而硬件RTL实现的是精确分段线性逼近,两者在-3到3区间差了千分之几,累积到后面几层就炸了。这个坑让我意识到,搞NPU的人必须对激活函数的硬件实现有直觉。今天聊聊GELU和Swish这两个在Transformer里用得飞起的激活函数,从硬件角度看看它们到底“友好”在哪里,又“坑”在哪里。先看数学本质GELU和Swish其实是一家人。GELU的数学形式是 x * Φ(x),其中Φ是标准正态分布的CDF。Swish则是 x * σ(βx),σ是sigmoid。当β≈1.7时,Swish和GELU的曲线几乎重合——这个结论来自Google Brain那篇Swish论文,实测确实如此。但数学上“几乎一样”不代表硬件实现上“几乎一样”。NPU里没有浮点除法,没有exp的精确计算,所有非线性函数都得用查找表或者分段多项式来近似。这里就出现了第一个分水岭:GELU的CDF函数在零点附近变化剧烈,而Swish的sigmoid相对平缓。硬件实现的核心矛盾NPU的激活函数单元通常放在MAC阵列后面,数据流是流水线式的。这意味着激活函数的计算延迟必须固定,不能有分支预测,不能有循环迭代。所有非线性函数都得拆成“查表+线性插值”或者“分段多项式”这两种模式。我