记一个神奇的Bug
多年以后,当Abraham凝视着一行行新时代的代码在屏幕上川流不息的时候,他会想起2019年4月17日那个不平凡夜晚,以及在那个夜晚他发现的那个不可思议的Bug。
虽然像无数个普普通通的夜晚一样,我在公司加班,一样ssh到公司在北京的服务器,但是发现resnet50的计算精度比上一版代码低了1%。一通着急忙慌的Debug之后无济于事,只能求助于Git来比较新旧版本异同。
由于精度降低的幅度很小,怀疑跟pool操作有关。最终发现是一个与一个未初始化的short整型数据有关。这个整型数据是pool操作的求和累加器,由于没有初始化,又由于某种机缘巧合,它的初始值是一个在0-20左右浮动的小值,这个小值在进行7×7的求和与average pool之后起到了抵消强制类型转换截断误差的作用(由于求和对象是ReLU之后的值,都是正值,故截断误差也都是正值)。
强制类型转换切记+0.5/-0.5来四舍五入。