特别是在Tensorflow将GEMMLOWP用于量化操作的情况下,我想在不同的位深度上运行量化操作。
This readme似乎有一些有用的信息,但是我仍然不太了解如何使用它或会产生什么影响-当它说最终数据类型仍然是uint8,但准确性较低时,确实会这仅意味着,例如7位算术运算符尽管存储在uint8变量中,仍将返回从0到127的值?不知道我是否在解释这一权利。
Tensorflow似乎利用了GemmLowP的MultiThreadGemm function-可以在/tensorflow/core/kernels/meta_support.cc中找到。
MultiThreadGemm函数采用一个Params结构;我看不到如何集成BitDepthParams,据我所知,它可以将精度设置为Params结构,以便针对任意位深度调整Tensorflow对MultiThreadGemm的使用。
任何见解/建议都会有用!
答案 0 :(得分:0)
当它说最终数据类型仍然是uint8,但是精度较低时,这是否仅意味着7位算术运算将尽管存储在uint8变量中却返回0到127的值?
是的,它说少于8位的值仅存储为完整的8位字节(在uint8_t中;将真正的4位或6位值的数组解压缩为与向量ALU / AVX兼容的东西将花费太高的成本/ GPU操作)。进一步说,输入(对于2017年2月之前的“现在”)仍是完整范围的8位整数:
输入/输出矩阵数据都是uint8的数据,范围从0到255,与BitDepth {Setting,Params}无关。
在打包阶段,gemlowp内部确实将输入数据重新打包到uint8_t存储中,范围更窄(在gemmlowp内部,在进行实际的gemm矩阵乘法之前,请在design.md - impact of low precision中检查gemm的一般伪代码,注意pack
和unpack
):
https://github.com/google/gemmlowp/blob/master/doc/less-than-8-bit.md#packing-stage
在这里,我们必须将输入矩阵值从其原始范围[0 ... 255]缩放到BitDepthParams指定的范围,即[0 ...(2 ^ N)-1],其中N为手头矩阵的位数(Lhs或Rhs)。例如,对于5位的位深度,我们需要缩小到[0 ... 31]。
输入和输出是uint8值的矩阵,但是在内部我们在累积int32值,最后只将它们转换回uint8。
2017年2月,不到8位的处理方式发生了巨大变化。
BitDepthParams
可能已在过去集成到库中,但是自2017年2月起提交的内容将“ 此'现在'状态变成过去(2017年2月)。”添加到{ {1}}文档,还删除了实际代码中对less-than-8-bit.md
的使用。现在可能输入的不是完整的8位范围。找不到内核选择的地方...
https://github.com/google/gemmlowp/commit/4746387c02f2b9542fe5d4a6ac4bb4d81f88ef15#diff-69cce824f316d701d9c3c23afcb00694“删除旧的重新量化少于8位的内容。”
删除旧的重新量化少于8位的东西。映射 将DefaultL7R5BitDepthParams设置为DefaultL8R8BitDepthParams,以便 此更改不会破坏任何依赖它的用户,因为整个 重新量化的重点是使它成为实现细节。
相反,从现在开始,仅使用小于8位的实际设置 具有选择其他GEMM内核的效果。换一种说法, 现在,用户有责任知道实际的位深度 (即范围)的8位值。作为交换 责任,低于8位深度的用户将享受 提高了相应内核的性能,而没有开销 重新量化。
BitDepthParams