[PTQ]均匀量化和非均匀量化

news2024/12/27 3:04:43

均匀量化和非均匀量化

基本概念

  • 量化出发点:使用整型数据类型代替浮点数据,从而节省存储空间同时加快推理速度。
  • 量化基本形式
    • 均匀量化:浮点线性映射到定点整型上,可以根据scale/offset完成量化/反量化操作。
    • 非均匀量化
      • PowersOfTwoQuant:浮点映射成2的指数位上,根据power计算完成量化/反量化操作。
      • AdditivePowersOfTwoQuant:浮点映射成多个不同指数的和,而整型表示应该是跟硬件实现相关(后续待定聊聊)
  • 不同形式的量化对不同的数据分布的拟合程度不一样

均匀量化(UniformQuant)

  • 特点:

    • 适合range较大,分布较均匀的分布
    • 最普遍/大众的量化方式,基本上市面上的加速器都是只支持均匀量化
    • 可以很容易从对称量化扩展到非对称量化
  • python代码实现如下所示

    # 均匀量化
    class UniformQuant:
        def __init__(self, 
                    bit=8) -> None:
            self.bit = bit
    
        def quant(self, input, min=0.0, max=1.0):
            max_q = np.power(2, self.bit) - 1
            input = np.clip(input, min, max)
            scale = (max - min) / max_q
            q = np.clip(np.round(input / scale), 
                        0,
                        max_q)
            return q, scale
    
        def dequant(self, q, scale):
            return (scale * q).astype(np.float32)
    
        def fakequant(self, input):
            q, scale = self.quant(input)
            fakequant_input = self.dequant(q, scale)
            return fakequant_input
    

PowersOfTwoQuant

  • 特点:

    • 适合以0.0为中心的高斯分布数据,靠近0.0附近的精度非常高
    • 提高bits数,无法提高整体的精度
  • python代码实现如下所示

    # PoT量化
    class PowersOfTwoQuant:
        def __init__(self, 
                    bit=8) -> None:
            self.bit = bit
    
        def quant(self, input, alpha):
            max_q = np.power(2, self.bit) - 1
            input = np.clip(input / alpha, 0.0, 1.0)
            q = list()
            for i in input:
                if i == 0.0:
                    q.append(0)
                else:
                    e_tmp = np.log(i) / np.log(2.0)
                    e_tmp = np.round(e_tmp + max_q)
                    e_tmp = np.clip(e_tmp, 0, max_q)
                    q.append(e_tmp)
            q = np.array(q, dtype=np.uint32)
            return q
    
        def dequant(self, q, alpha):
            max_q = np.power(2, self.bit) - 1
            input = list()
            for i in q:
                if i == 0:
                    input.append(0.0)
                else:
                    input.append(np.power(2.0, i - max_q))
            
            input = np.array(input, dtype=np.float32)
            input = alpha * input
            return input
    
        def fakequant(self, input, alpha = None):
            if alpha is None:
                alpha = input.max()
            q = self.quant(input, alpha)
            fakequant_input = self.dequant(q, alpha)
            return fakequant_input
    
    

AdditivePowersOfTwoQuant

  • 特点:

    • 0.0附近的精度比均匀分布高
    • 提高bits数,可以提高整体的精度
    • 计算较为复杂,推理加速应该需要专门设计实现方式
  • python代码实现如下所示

    # APoT量化
    class AdditivePowersOfTwoQuant:
        def __init__(self, 
                    bit=8,
                    k=2) -> None:
            self.bit = bit
            self.k = k
            self.n = int(self.bit/self.k)
            self.p = np.array(self.gen_table(), dtype=np.float32)
            self.sort_values = self.get_all_values()
            self.sort_values.sort()
            # self.power_set = build_power_value(self.bit, additive=False)
            # self.power_set = self.power_set.detach().numpy()
    
        def get_all_values(self):
            m,n = list(self.p.shape)
            values = self.recursion_add(self.p.tolist())
            return np.array(values, dtype=np.float32)
        
    
        def recursion_add(self, input_list, callback=lambda a,b:a+b):
            # [list1, list2]
            res = list()
            if len(input_list) == 2:
                list1, list2 = input_list
                for a in list1:
                    for b in list2:
                        res.append(callback(a,b))
                return res
            elif len(input_list) > 3:
                tmp_input_list = input_list[:-2]
                tmp_res = self.recursion_add(input_list[-2:])
                tmp_input_list.append(tmp_res)
                return self.recursion_add(tmp_input_list)
            
    
        def gen_table(self):
            p = list()
            for i in range(self.n):
                one_lines_p = list()
                one_lines_p.append(0.0)
                for j in range(int(math.pow(2, self.k) - 2 + 1)):
                    one_lines_p.append(math.pow(2, -(i+j*self.n)))
                p.append(one_lines_p)
            return p
    
        def quant(self):
            # 待定
            pass
    
        def dequant(self):
            # 待定
            pass
    
        def fakequant(self, input):
            scale = input.max() / self.sort_values.max()
            fakequant_input = list()
            input = input / scale
            for v in input:
                argmin_index = np.argmin(np.abs(self.sort_values - v))
                tmp_value = self.sort_values[argmin_index]
                fakequant_input.append(tmp_value)
            fakequant_input = np.array(fakequant_input, dtype=np.float32) * scale
            return fakequant_input
    
    

试验展示

  • 数据分布在[0.0, 1.0]之间,全覆盖

  • 下图表示三种量化方式的x-fakequant_y的映射关系

    在这里插入图片描述

代码工程下载

下载地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1242981.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

containerd Snapshots功能解析

containerd Snapshots功能解析 snapshot是containerd的一个核心功能,用于创建和管理容器的文件系统。 本篇containerd版本为v1.7.9。 本文以 ctr i pull命令为例,分析containerd的snapshot “创建” 相关的功能。 ctr命令 ctr image相关命令的实现在cmd…

OpenAI“宫斗”新进展!Sam Altman将重返OpenAI担任首席执行官 董事会成员改动

在经过激烈的五天讨论和辩论之后,高调人工智能初创公司OpenAI宣布,其联合创始人之一Sam Altman将回归担任首席执行官。这一决定是对上周Altman突然被解雇的回应,该决定引起了极大的关注和讨论。 OpenAI表示,他们已经达成了与Altm…

低代码平台推荐:五大低代码厂商谁的模式更“合适”

随着数字化时代的到来,低代码开发平台作为提高数字生产力的工具正受到越来越多企业的关注,市面上的低代码产品和厂商更是“乱花渐欲迷人眼”。 各家产品不仅功能各有不同,甚至商机都有区别的情况,如何做好产品选型已然成了采购企…

2023年国内好用的企业网盘推荐

2023年企业网盘俨然已经成为了各个企业团队的标配了,那么2023年国内有什么好用的企业网盘吗?2023国内哪个企业网盘好用? 国内哪个企业网盘好用? 由于不同行业企业对于企业网盘的具体需求点不同,因此我们无法从功能上评…

idea 2023 安装配置 Gradle8.4

官网:https://gradle.org 下载 Gradle8.4 https://gradle.org/releases/ 解压到本地,到 gradle-8.4\init.d 目录下新建文件:init.gradle 这里有个坑,编译报http协议安全的问题,解决办法,加入&#xff1…

【EI会议征稿】第十一届先进制造技术与材料工程国际学术会议 (AMTME 2024)

JPCS独立出版/高录用快检索/院士杰青云集 第十一届先进制造技术与材料工程国际学术会议 (AMTME 2024) 2024 11th International Conference on Advanced Manufacturing Technology and Materials Engineering 第十一届先进制造技术与材料工程国际学术会议 (AMTME 2024) 定于…

前端处理返回数据为数组对象且对象嵌套数组并重名的数据,合并名称并叠加数据

前端处理返回数据为数组对象且对象嵌套数组并重名的数据,合并名称并叠加数据 var newList[]; var table{}; var dataObj{}; var finalList[]; var tableData[{brName:营业部,dateStr:2023-11-23,tacheArr:[{dealCnt:20,tacheName:奔驰}]},{brName:营业部,dateStr:2…

软件开发团队如何确保团队成员与项目进度一致?

在软件开发团队中,确保团队成员的利益与项目进度保持一致,可以采取以下措施: 建立基础流程:建立几个最主要的流程,如任务跟踪、开发效率提升、任务完成等,可以帮助小团队从无序逐步进入有序。 关注员工反馈…

【逆向】NahamCon CTF -Click Me Writeup(BridaFrida Hook 拿Flag)

文章目录 前言一、样式与功能点二、反编译三、Frida Get Flag四、BurpSuite插件-Brida总结 前言 第一次做外国CTF比赛的mobile challenge 题,题目就是一个安卓的apk安装包。顺便记录一下代码分析过程以及分享两种不同的解题思路。 提示:以下是本篇文章正…

选对软件公司,助力小程序商城腾飞

选择一家合适的软件公司对于小程序商城的开发和运营至关重要。在众多的软件公司中,如何找到最适合自己的合作伙伴呢?本文将从实际需求、公司实力、案例展示、服务态度和价格等五个方面,为您解析如何选择合适的软件公司。 一、明确实际需求 在…

用「超舒适」突围,星纪元 ES 加量不加价

在 2023 广州车展上,星途星纪元 ES 正式开启预售,新车预售区间 24.8-35.8 万元,共推出五款车型配置。 外观方面,星纪元 ES 前脸采用了封闭式的设计,前大灯组采用了流行的贯穿式设计搭配矩阵大灯,使得整个灯…

cefsharp119.4.30(cef119.4.3Chromium119.0.6045.159)版本升级体验支持x86_h264及其他多个h264版本

Cefsharp119.4.30,cef119.4.3,Chromium119.0.6045.159 此更新包括一个高优先级安全更新 This update includes a high priority security update. 说明:此版本119.4.3支持x86_H264视频播放(需要联系我),其他版本。.NETFramework 4.6.2 NuGet Gallery | CefSharp.WinForms …

Selenium(12):层级定位_通过父元素找到子元素

层级定位 在实际的项目测试中,经常会遇到无法直接定位到需要选取的元素,但是其父元素比较容易定位,通过定位父元素再遍历其子元素选择需要的目标元素,或者需要定位某个元素下所有的子元素。 层级定位的思想是先定位父对象&#xf…

外包干了4年,技术算是没了...

先说一下自己的情况。大专生,19年通过校招进入湖南某软件公司,干了接近3年的测试,今年年上旬,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了三年&#xff0c…

企业邮箱即时提醒服务推荐

现在用企业邮箱比较多,但是不能即时提醒,总是误事,什么邮箱可以即时提醒呢?随着工作和生活节奏的加快,传统的电子邮件系统由于不能即时提醒,往往会导致重要邮件的漏接,从而引发一系列的麻烦和误…

java--继承快速入门

1.什么是继承 java中提供了一个关键字extends,用这个关键字,可以让一个类和另一个类建立其父子关系。 2.继承的特点 子类能继承父类的非私有成员(成员变量,成员方法)。 3.继承后对象的创建 子类的对象是由子类、父类共同完成的。 4.继承的…

贝锐向日葵:独家算法如何支撑不断地产品创新?

作为国民级的专业远程控制品牌,贝锐旗下的“向日葵远程控制”一直在远程控制领域不断积累创新。 近年来,远程控制软件本身开始成为企业的主流远程业务工具以及个人场景下的日常必备软件,向日葵远程控制也在不断地完善并创新产品。 比如在前…

全网最详细的安装pytorch GPU方法,一次安装成功!!包括安装失败后的处理方法!

文章目录 前提---查看是否有NVIDIV英伟达显卡【笑哭】一、查看电脑的显卡驱动版本方法一:在cmd命令窗口中输入nvidia-smi,可以发现版本为12.2方法2:点击NVIDIA控制面板→系统信息 二、安装CUDA方法1: 在pytorch官网https://pytorc…