精华内容
下载资源
问答
  • [转]消除FPGA设计毛刺问题

    千次阅读 2014-10-23 13:05:00
    一.FPGA(Field ...在FPGA的设计,毛刺现象是长期困扰电子设计工程师的设计问题之一,是影响工程师设计效率和数字系统设计有效性和可靠性的主要因素。由于信号在FPGA的内部走线和通过逻辑单元时造成的延迟,...

    一.FPGA(Field Programmable Gate Array)以其容量大、功能强以及可靠性高等特点,在现代数字通信系统中得到广泛的应用。采用FPGA设计数字电路已经成为数字电路系统领域的主要设计方式之一。在FPGA的设计中,毛刺现象是长期困扰电子设计工程师的设计问题之一,是影响工程师设计效率和数字系统设计有效性和可靠性的主要因素。由于信号在FPGA的内部走线和通过逻辑单元时造成的延迟,在多路信号变化的瞬间,组合逻辑的输出常常产生一些小的尖峰,即毛刺信号,这是由FPGA内部结构特性决定的。毛刺现象在FPGA的设计中是不可避免的,有时任何一点毛刺就可以导致系统出错,尤其是对尖峰脉冲或脉冲边沿敏感的电路更是如此。因此,克服和解决毛刺问题对现代数字系统设计尤为重要。本文从FPGA的原理结构的角度探讨了产生毛刺的原因及产生的条件,在此基础上,总结了多种不同的消除方法,在最后结合具体的应用对解决方案进行深入的分析。 

    1 毛刺产生的原因
     
    以图1的例子分析毛刺产生的起因:图1是一个3位同步加法计数器,当使能端为高电平时,在每个时钟上升沿时刻QA、QB、QC从000逐步变到111,进入到全1状态后,进位输出端输出半个时钟脉冲宽度的高电平,但从图2仿真结果中可以看到在011变化到100时刻ROC出现了尖脉冲,即毛刺。 

    1 3位计数器 

    2 仿真结果 

    Xilinx的FPGA为例分析其内部结构,如图3所示。 

    3 FPGA的内部结构 

    FPGA芯片是由可构造的输入输出块(Input/OutputBlock,IOB)、可构造逻辑块(Cinfigurable Logic Block,CLB)和可编程连线资源(Programmable Interconnect Array,PIA)3种可构造单元构成的。IOB位于芯片内部四周,在内部逻辑阵列与外部芯片封装引脚之间提供一个可编程接口,他主要由逻辑门、触发器和控制元组成。CLB组成了FPGA的核心阵列,能完成用户指定的逻辑功能;每个CLB主要有一个组合逻辑、几个触发器、若干个多选一电路和控制单元组成;PIA位于芯片内部的逻辑块之间,经编程后形成连线网络,用于芯片内部逻辑间的相互连接,并在他们之间传递信息。从图3中可以看出,对于不同的输入1、2,到逻辑块(M)的走线可能是不同的,这就造成了输入信号的延迟,假设1、2同时变化,由于延迟的存在,到达M时就有先有后(这种现象称为竞争),在逻辑输出端就可能会有险象(也称冒险),即产生了毛刺。在上述例子中的011状态,假设QA与QB同时从1变化到0,而QC提前了2ns从0变到1,产生一个2ns的高电平,这就是毛刺。也就是说,在FPGA设计中,毛刺产生的根本原因是信号在芯片内部走线时产生的延迟。 

    2 毛刺产生的条件
     
    借助同样的例子来分析毛刺产生的条件。QA,QB,QC在每一个时钟上升沿同时发生翻转,但实际中由于延迟的存在,并不能保证QA,QB,QC到D触发器的布线长短一致。如果QC比QA,QB提前了2ns,这就形成了2ns的全1状态,称为“假象全1”,进而导致进位输出产生一个尖脉冲。值得注意的是,在3变到4即011到100时,3位中有2位同时发生翻转,即在同一时刻有大于一个的信号发生改变。由于延迟的作用,多个信号到达终点的时间有先有后,形成了竞争,由竞争产生的错误输出就是毛刺。所以,毛刺发生的条件就是在同一时刻有多个信号输入发生改变。 

    3 消除毛刺的方法 

    知道了毛刺产生的条件,就可以通过改变设计,破坏其条件来减少毛刺的发生。例如,利用格雷码计数器每次输出只有一位跳变的特性,代替普通的二进制计数器,避免了毛刺的产生。还可以对电路进行改进,以消除毛刺对系统的影响。下面对各种方法做分别介绍

    3.1 利用冗余项法 
    利用冗余项消除毛刺有2种方法:代数法和卡诺图法,两者都是通过增加冗余项来消除险象,只是前者针对于函数表达式而后者针对于真值表。以卡诺图为例,若两个卡诺圆相切,其对应的电路就可能产生险象。因此,修改卡诺图,在卡诺图的两圆相切处增加一个圆,以增加多余项来消除逻辑冒险。但该法对于计数器型产生的毛刺是无法消除的。 

    3.2 采样法 
    由于冒险多出现在信号发生电平跳变的时刻,即在输出信号的建立时间内会产生毛刺,而在保持时间内不会出现,因此,在输出信号的保持时间内对其进行采样,就可以消除毛刺信号的影响,常用的采样方法有2种:一种使用一定宽度的高电平脉冲与输出相与,从而避开了毛刺信号,取得输出信号的电平值。这种方法必须保证采样信号在合适的时间产生,并且只适用于对输出信号时序和脉冲宽度要求不严的情况。另一种更常见的方法叫锁存法,是利用D触发器的输入端D对毛刺信号不敏感的特点,在输出信号的保持时间内,用触发器读取组合逻辑的输出信号。由于在时钟的上升沿时刻,输出端Q=D,当输入的信号有毛刺时,只要不发生在时钟的上升沿时刻,输出就不会有毛刺。这种方法类似于将异步电路转化为同步电路,实现简单,但同样会涉及到时序问题。 

    3.3 吸收法 
    由于产生的毛刺实际上是高频窄脉冲,故增加输出滤波,在输出端接上小电容C就可以滤除毛刺。但输出波形的前后沿将变坏,在对波形要求较严格时,应再加整形电路,该方法不宜在中间级使用。 

    3.4 延迟法 
    因为毛刺最终是由于延迟造成的,所以可以找出产生延迟的支路。对于相对延迟小的支路,加上毛刺宽度的延迟可以消除毛刺。但有时随着负载增加,毛刺会继续出现,而且,当温度变化,所加的电压变化或要增加逻辑门时,所加的延迟是不同的,必须重新设计延迟线,因而这种方法也是有局限性的。而且采用延迟线的方法产生延迟会由于环境温度的变化而使系统可靠性变差。 

    3.5 硬件描述语言法 
    这种方法是从硬件描述语言入手,找出毛刺产生的根本原因,改变语言设计,产生满足要求的功能模块,来代替原来的逻辑功能块。在图1电路中,一个3位计数器可能会在011到100和101到110发生跳变时产生毛刺,究其原因是因为一次有2位发生跳变,可以采用VHDL语言对计数器编写如下,产生的计数模块代替原来普通的计数器。 
    subdesignmodcount 
     (clk,reset:input;q[2110]:output;) 
    variable 
    counter3 
    :MACHINEOFBITS(r[2110]) 
     WITHSTATES(r0=B"101", 
    r1=B"100", 
    r2=B"000", 
    r3=B"001", 
    r4=B"011", 
    r5=B"010", 
    r6=B"110", 
    r7=B"111"); 
     begin 
      q[ ]=rr[ ]; 
    counter31reset=reset; 
    counter31clk=clk; 

    转载于:https://www.cnblogs.com/adxiaowei/p/4045532.html

    展开全文
  • FPGA学习之毛刺问题

    千次阅读 2020-02-14 18:48:44
    在FPGA的设计,毛刺现象是长期困扰电子设计工程师的设计问题之一,是影响工程师设计效率和数字系统设计有效性和可靠性的主要因素。由于信号在FPGA的内部走线和通过逻辑单元时造成的延迟,在多路信号变化的瞬间,组合...

    在FPGA的设计中,毛刺现象是长期困扰电子设计工程师的设计问题之一,是影响工程师设计效率和数字系统设计有效性和可靠性的主要因素。由于信号在FPGA的内部走线和通过逻辑单元时造成的延迟,在多路信号变化的瞬间,组合逻辑的输出常常产生一些小的尖峰,即毛刺信号,这是由FPGA内部结构特性决定的。毛刺现象在FPGA的设计中是不可避免的,有时任何一点毛刺就可以导致系统出错,尤其是对尖峰脉冲或脉冲边沿敏感的电路更是如此。因此,克服和解决毛刺问题对现代数字系统设计尤为重要。本文从FPGA的原理结构的角度探讨了产生毛刺的原因及产生的条件,在此基础上,总结了多种不同的消除方法,在最后结合具体的应用对解决方案进行深入的分析。

    1 毛刺产生的原因
    1.1 建立时间和保持时间
    建立时间(setup time)是指在触发器的时钟信号上升沿到来以前,数据稳定不变的时间,如果建立时间不够,数据将不能在这个时钟上升沿被打入触发器;保持时间(hold time)是指在触发器的时钟信号上升沿到来以后,数据稳定不变的时间, 如果保持时间不够,数据同样不能被打入触发器, 如图1。 数据稳定传输必须满足建立和保持时间的要求,当然在一些情况下,建立时间和保持时间的值可以为零。
    图1 建立时间与保持时间
    1.2 竞争和冒险
    FPGA芯片是由可构造的输入输出块(Input/OutputBlock,IOB)、可构造逻辑块(Cinfigurable Logic Block,CLB)和可编程连线资源(Programmable Interconnect Array,PIA)3种可构造单元构成的。IOB位于芯片内部四周,在内部逻辑阵列与外部芯片封装引脚之间提供一个可编程接口,他主要由逻辑门、触发器和控制元组成。CLB组成了FPGA的核心阵列,能完成用户指定的逻辑功能;每个CLB主要有一个组合逻辑、几个触发器、若干个多选一电路和控制单元组成;PIA位于芯片内部的逻辑块之间,经编程后形成连线网络,用于芯片内部逻辑间的相互连接,并在他们之间传递信息。信号在FPGA器件内部通过连线和逻辑单元时,都有一定的延时。延时的大小与连线的长短和逻辑单元的数目有关,同时还受器件的制造工艺、 工作电压、温度等条件的影响。信号的高低电平转换也需要一定的过渡时间。由于存在这两方面因素,多路信号的电平值发生变化时,在信号变化的瞬间,组合逻辑 的输出有先后顺序,并不是同时变化(及竞争现象),往往会出现一些不正确的尖峰信号,这些尖峰信号称为"毛刺"。如果一个组合逻辑电路中有"毛刺"出现,就说明该电路存 在"冒险"。(与分立元件不同,由于PLD内部不存在寄生电容电感,这些毛刺将被完整的保留并向下一级传递,因此毛刺现象在PLD、FPGA设计中尤为突 出)也就是说,在FPGA设计中,毛刺产生的根本原因是信号在芯片内部走线时产生的延迟。

    2 毛刺产生的条件
    由于延迟的作用,多个信号到达终点的时间有先有后,形成了竞争,由竞争产生的错误输出就是毛刺。所以,毛刺发生的条件就是在同一时刻有多个信号输入发生改变。

    3 消除毛刺的方法
    知道了毛刺产生的条件,就可以通过改变设计,破坏其条件来减少毛刺的发生。例如,利用格雷码计数器每次输出只有一位跳变的特性,代替普通的二进制计数器,避免了毛刺的产生。还可以对电路进行改进,以消除毛刺对系统的影响。下面对各种方法做分别介绍:
    3.1 利用冗余项法
    利用冗余项消除毛刺有2种方法:代数法和卡诺图法,两者都是通过增加冗余项来消除险象,只是前者针对于函数表达式而后者针对于真值表。以卡诺图为例,若两个卡诺圆相切,其对应的电路就可能产生险象。因此,修改卡诺图,在卡诺图的两圆相切处增加一个圆,以增加多余项来消除逻辑冒险。但该法对于计数器型产生的毛刺是无法消除的。

    3.2 采样法
    由于冒险多出现在信号发生电平跳变的时刻,即在输出信号的建立时间内会产生毛刺,而在保持时间内不会出现,因此,在输出信号的保持时间内对其进行采样,就可以消除毛刺信号的影响,常用的采样方法有2种:一种使用一定宽度的高电平脉冲与输出相与,从而避开了毛刺信号,取得输出信号的电平值。这种方法必须保证采样信号在合适的时间产生,并且只适用于对输出信号时序和脉冲宽度要求不严的情况。另一种更常见的方法叫锁存法,是利用D触发器的输入端D对毛刺信号不敏感的特点,在输出信号的保持时间内,用触发器读取组合逻辑的输出信号。由于在时钟的上升沿时刻,输出端Q=D,当输入的信号有毛刺时,只要不发生在时钟的上升沿时刻,输出就不会有毛刺。这种方法类似于将异步电路转化为同步电路,实现简单,但同样会涉及到时序问题。

    3.3 吸收法
    由于产生的毛刺实际上是高频窄脉冲,故增加输出滤波,在输出端接上小电容C就可以滤除毛刺。但输出波形的前后沿将变坏,在对波形要求较严格时,应再加整形电路,该方法不宜在中间级使用。

    3.4 延迟法
    因为毛刺最终是由于延迟造成的,所以可以找出产生延迟的支路。对于相对延迟小的支路,加上毛刺宽度的延迟可以消除毛刺。但有时随着负载增加,毛刺会继续出现,而且,当温度变化,所加的电压变化或要增加逻辑门时,所加的延迟是不同的,必须重新设计延迟线,因而这种方法也是有局限性的。而且采用延迟线的方法产生延迟会由于环境温度的变化而使系统可靠性变差。

    3.5 硬件描述语言法
    这种方法是从硬件描述语言入手,找出毛刺产生的根本原因,改变语言设计,产生满足要求的功能模块,来代替原来的逻辑功能块。

    3.6 用verilog代码,实现消除一个glitch
    (1) 滤掉小于1个周期glitch的原理图如下:
    在这里插入图片描述
    verilog代码实现如下:

    module digital_filter_(clk_in,rst,host_rst,host_rst_filter);
    input  clk_in;
    input  rst;
    input  host_rst;
    output host_rst_filter;
     
    reg host_rst_d1;
    reg host_rst_d2;
     
    always@(posedge clk_in or negedge rst)
      begin
        if(!rst)
        begin
            host_rst_d1 <= 1'b1;
            host_rst_d2 <= 1'b1;
           end
        else
          begin
            host_rst_d1 <= host_rst;
            host_rst_d2 <= host_rst_d1;
     
          end
      end
     
    assign host_rst_filter = host_rst_d1 | host_rst_d2;
    endmodule
    

    (2)滤掉大于1个周期且小于2个周期glitch的原理图如下:
    在这里插入图片描述
    verilog代码实现如下:

    module digital_filter_(clk_in,rst,host_rst,host_rst_filter);
    input  clk_in;
    input  rst;
    input  host_rst;
    output host_rst_filter;
     
    reg host_rst_d1;
    reg host_rst_d2;
    reg host_rst_d3;
     
    always@(posedge clk_in or negedge rst)
      begin
        if(!rst)
        begin
            host_rst_d1 <= 1'b1;
            host_rst_d2 <= 1'b1;
            host_rst_d3 <= 1'b1;
          end
        else
      begin
            host_rst_d1 <= host_rst;
            host_rst_d2 <= host_rst_d1;
            host_rst_d3 <= host_rst_d2;
           end
      end
     
    assign host_rst_filter = host_rst_d1 | host_rst_d2 | host_rst_d3;
     
    endmodule
    

    参考:
    (1)http://www.cnblogs.com/adxiaowei/p/4045532.html
    (2)https://wenku.baidu.com/view/9b67c5d649649b6648d747ed.html
    (3)https://blog.csdn.net/wangyanchao151/article/details/83374982

    展开全文
  • 作者:jasonzxpan,腾讯 IEG 运营开发工程师本文排查一个Linux 机器 CPU 毛刺问题,排查过程不变更进程状态、也不会影响线上服务,最后还对 CPU 毛刺带来的风险进行...

    作者:jasonzxpan,腾讯 IEG 运营开发工程师

    本文排查一个Linux 机器 CPU 毛刺问题,排查过程中不变更进程状态、也不会影响线上服务,最后还对 CPU 毛刺带来的风险进行了分析和验证。

    本文中提到 CPU 统计和产生 core 文件的工具详见 simple-perf-tools 仓库。

    问题描述

    某服务所在机器统计显示,其 CPU 使用率在高峰时段出现毛刺。

    暂时未收服务调用方的不良反馈。

    初步排查

    查看 CPU 1 分钟平均负载,发现 1 分钟平均负载有高有低,波动明显。说明机器上有些进程使用 CPU 波动很大。

    登录机器排查进程,使用top指令。因为 CPU 会明显上升,重点怀疑使用 CPU 总时间高的进程,在打开 top 后,使用shift +t可以按照 CPU TIME 进行排序。

    直观的看,有几个 spp_worker 相关的进程使用 CPU TIME 相对较高。

    第一个进程因为启动的时间比较长,所以 CPU TIME 也比较大。可以使用下面的脚本,计算各个进程从各自拉起后 CPU 使用率:

    uptime=`awk '{print $1}' /proc/uptime` # why is it too slow indocker?
    hertz=`zcat /proc/config.gz | grep CONFIG_HZ= |awk -F"=" '{print $2}'`
    awk -v uptime=$uptime -v hertz=$hertz -- '{printf("%d\t%s\t%11.3f\n", $1, $2, (100 *($14 + $15) / (hertz * uptime - $22)));}' /proc/*/stat 2> /dev/null | sort  -gr -k +3 | head -n 20
    

    看到的也是这些 spp_worker 使用 CPU 相对要高一些:

    选其中的一个 PID 为 45558 的 Worker 进程监控器 CPU 使用率:

    可以发现其 CPU 大部分情况很低,但是在某一个时间点会升高,持续 1 秒左右。而且大部分时间是耗费在用户态,而非系统调用。

    而《Linux Agent 采集项说明 - CPU 使用率》中描述的 CPU 使用率的采样策略为:

    Linux Agent 每分钟会采集 4 次 15 秒内的 CPU 平均使用率。为了避免漏采集 CPU 峰值,网管 Agent 取这一分钟内四次采集的最大值上报。

    因为采样可能采到高点或者低点,当 1 分钟内出现 CPU 飙升,则会表现为尖峰;如果四次都没有出现飙升,则表现为低谷。

    至此,已经能确认是这批 Worker 进程引起了这种毛刺,但具体是哪部分代码有问题还需要进一步排查。

    进一步排查

    前边确认了没有太多的系统调用,所以不必使用strace工具。

    使用perf工具

    使用perf工具进行查看。具体的命令是perf top -p 45558,在低 CPU 使用率的时候:

    但是当 CPU 飚上去的时候,perf采样的位置变成如下这样:

    看一下红框的位置,可以发现可能是配置更新部分有问题,因为:

    • 这个地方 Protobuf 特别多的地方,在做更新的操作(有MergeFrom,有Delete

    • 有大量的用到了std::map(有std::_Rb_tree,有字符串比较)

    通过观察perf结果的方法,虽然能够猜测大计算量的位置,但是有两个不便之处:

    • 如果 CPU 高的情况发生概率很低,人为观察比较耗时

    • 不能明确的知道,具体在哪个文件的哪个函数

    使用gcore

    最初统计的时候,发现 CPU 高的情况会出现 1 秒多的时间,如果发现 CPU 高负载时,直接调用gcore {pid}的命令,可以保留堆栈信息,明确具体高负载的位置。

    将使用 gcore 的指令,添加到统计工具中取,设置 CPU 上门限触发。

    通过gdb看了几个 coredump 文件,发现堆栈和函数调用基本一致。可以明确的看到,大量的耗时发生在了AddActInfoV3这一函数中:

    到此位置,我们明确了高计算量发生的具体位置。

    风险点

    CPU 突然飙升是否存在风险呢?是不是计算资源充足的时候,就不会有问题呢?

    这个例子中,使用的是 SPP 微线程功能,每个 Worker 进程只启用一个线程。

    如果仅仅是因为高计算量卡住 CPU,正常处理请求的逻辑将很难被调度到。这样势必会造成处理请求的延迟增大,甚至有超时返回的风险。

    使用 spp 的cost_stat_tool工具

    利用 spp 自带的统计工具印证这一风险点,查看 worker 处理前端请求时延统计信息,执行命令./cost_stat_tool -r 1

    上边的例子中,统计发生配置更新前后的 5 秒钟内,worker 处理的 231 个请求中,有 3 个请求的处理时间超过 500ms,远高于普通请求。

    使用tcpdump抓包确认

    因该服务没有打开详细的日志,想要进一步验证超过 500ms 的这些请求也是正常处理的请求,而非异常请求,可以通过抓包来分析。

    tcpdump -i any tcp port 20391 -Xs0 -c 5000 -w service_spp.pcap
    

    通过 wireshark 打开,需要过滤出返回时间 - 请求时间 > 500ms的相关请求。翻译成 wireshark 过滤器的表达式则是:

    tcp.time_delta > 0.5 && tcp.dstport != 20391
    

    过滤出一条符合条件的请求:

    在该条记录上右键 -> Follow -> TCP Stream,可以查看该请求前后的 IP 包:

    上边 4 个包分别是:

    1. +0ms 客户端发送请求至服务端

    2. +38ms 服务端回复 ACK,无数据

    3. +661ms 服务端发送返回至客户端

    4. +662ms 客户端回复 ACK

    详细看了包中的内容为一条普通请求,逻辑简单,应该在 20ms 内返回。而此时的该进程使用 CPU 也确实为高负载的情况:

    上述统计相互印证:

    • CPU 高时,正常的网络请求也会被阻塞住(回复 ACK 需要 38ms,低于 40ms,与TCP 延迟确认无关)

    • 平时只需要 20ms 能返回的请求,耗时了 660ms

    CPU 突然飚高有风险,需要认真对待。

    欢迎关注我们的视频号:腾讯程序员

    展开全文
  • 利用最优权值系数,将灰色理论、人工神经网络和遗传算法有机结合,构建组合算法,依据3种数学方法建立3种组合模型:组合算术平均模型、组合平方和平均模型以及组合比例平均模型,并分别将3种组合模型应用于45钢铣削毛刺的...
  • 前言在点击率CTR(Click Through Rate)预估算法的推荐场景使用 Tensorflow Serving热更新较大模型时会出现短暂的延时毛刺,导致业务侧超时,降低算法效果...

    前言

    在点击率CTR(Click Through Rate)预估算法的推荐场景中使用 Tensorflow Serving热更新较大模型时会出现短暂的延时毛刺,导致业务侧超时,降低算法效果,为了解决这个问题,爱奇艺深度学习平台团队经过多个阶段的优化实践,最后对 TF Serving 和 Tensorflow 的源码进行深入优化,将模型热更新时的毛刺现象解决,本文将分享Tensorflow Serving的优化细节,希望对大家有帮助。

    背景介绍

    [Tensorflow Serving](https://github.com/tensorflow/serving) 是谷歌开源的用来部署机器学习模型的高性能推理系统。它主要具备如下特点:

        - 同时支持 gRPC 和 HTTP 接口

        - 支持多模型,多版本

        - 支持模型热更新和版本切换

    爱奇艺深度学习平台上大量的 CTR 推荐类业务使用 Tensorflow Serving 来部署线上推理服务。

    CTR 类业务对线上服务的可持续性要求很高,如果模型升级时要中断服务是不可接受的,因此 TF Serving 的模型热更新功能对这样的业务场景提供了很大的帮助,可以避免重启容器来做模型升级。

    但是,随着业务对模型更新实时性的要求越来越高,我们发现,模型热更新时出现的短暂客户端请求超时现象(称之为毛刺现象)变成进一步提升实时性的一个比较大的障碍。

    模型更新时的毛刺现象

    先来看一下,

    什么是模型更新时的毛刺现象?

    下面这张图是我们在 TF Serving 代码中增加了 [Bvar](https://github.com/apache/incubator-brpc/blob/master/docs/cn/bvar.md) 来查看内部请求的延迟情况。图中是延迟的分位比,延迟分位值分别为 `[p80, p90, p99, p999]`,单位是微秒。

    从图中可以看到,在模型更新前后,`p999` 的延迟都在 `30ms` 以下。但是,在模型更新的瞬间,`p999` 延迟突然抖动到 `120ms+`,持续了大概 10 秒时间,这就是**毛刺现象**,反应到客户端就是会产生请求超时失败。

    为了完全解决这个问题,爱奇艺深度学习平台经过多个阶段的深入优化,最后将模型更新时的毛刺现象解决。

    TF Serving 的模型更新过程

    工欲善其事必先利其器,我们先来看看 TF Serving 内部的模型更新过程。

    如上图,`Source` 会启动一个线程来不断查看模型文件,然后将发现的新模型构建相应的 `Servable` 数据结构放到 `Aspired Versions` 的队列中去。

    `DynamicManager` 也会启动一个线程,来不断查看 `Aspired Versions` 队列是否有需要处理的请求,根据配置的 `Version Policy` 来执行模型更新策略,最后通过 `SessionBundle` 来执行模型的加载和卸载。

    `Version Policy` 默认为 `AvailabilityPreservingPolicy`,该 policy 的特点是当有新的模型加入时,会保证至少有一个可服务的模型版本,当新版本加载完成后,再卸载旧版本,这样可以最大程度的保证模型的可服务性。

    举例子来讲,如果只支持一个模型版本,当前版本是 2,如果有新的版本 3 加入,那么会先加载版本 3,然后再卸载版本 2。

    接下来,详细看一下 TF Serving 的模型加载过程,主要分成以下几个步骤:

    1. 创建一个 DirectSession

    2. 将模型的 Graph 加载到 Session 中

    3. 执行 Graph 中的 Restore Op 来将变量从模型中读取到内存

    4. 执行 Graph 中的 Init Op 做相关的模型初始化

    5. 如果配置了 Warmup,执行 Warmup 操作,通过定义好的样本来预热模型

    Tensorflow 的模型执行有个非常显著的特点是 lazy initialization,也就是如果没有 Warmup,当 TF Serving 加载完模型,其实只是加载了 Graph 和变量,Graph 中的 OP 其实并没有做初始化,只有当客户端第一次发请求过来时,才会开始初始化 OP。

      问题的初步优化 ·

    从上面的分析来看,可以看到初步的解决方案,那就是做模型的 Warmup,具体方案如下:

    1. 配置模型 Warmup,模型目录中增加 tf_serving_warmup_requests 文件

    2. 使用独立线程来做模型的加载和卸载操作,配置 `num_unload_threads` 和 `num_load_threads`

    模型如何做 Warmup 详细请参考 TF 的文档 [SavedModel Warmup](https://www.tensorflow.org/tfx/serving/saved_model_warmup)。

    第二项优化主要是参考美团的文章[基于 TensorFlow Serving 的深度学习在线预估](https://tech.meituan.com/2018/10/11/tfserving-improve.html)。

    我们来对比一下优化前后的区别:

    可以看到,使用上面的优化,抖动的延迟减少了几个数量级,效果很明显。

    问题的进一步优化·

    虽然上面的优化将模型更新时的毛刺降低到只有 120ms+,但是这个仍然会对客户端的请求产生超时现象,如果模型更新的频率不高,比如一天更新一次,那么基本上是可以接受的。

    但是,如果业务对模型更新的实时性到一个小时以内,甚至更高,那么就必须进一步解决毛刺问题。我们不得不继续思考,剩下的这个毛刺是由于什么原因产生的?

    TF Serving 是一个计算密集型的服务,对可能产生影响的因素,我们做了如下猜测:

    • 算原因:是不是新模型的初始化,包括 Warmup 的计算,影响了推理请求?

    • 内存原因:是不是模型更新过程中的内存分配或释放产生锁而导致的?

    • 或者两者都有?

    计算原因分析

    先来分析一下计算方面的原因,如果模型加载会影响到推理请求,那么能不能将模型的加载也用独立的线程来做?

    经过调研 TF Serving 的源码,我们发现了这样的参数,原来 TF 已经考虑到这样的因素。

    ```

      // If set, session run calls use a separate threadpool for restore and init

      // ops as part of loading the session-bundle. The value of this field should

      // correspond to the index of the tensorflow::ThreadPoolOptionProto defined as

      // part of `session_config.session_inter_op_thread_pool`.

      google.protobuf.Int32Value session_run_load_threadpool_index = 4;

    ```

    通过配置 `session_inter_op_thread_pool` 并设置 `session_run_load_threadpool_index` 可以将模型的初始化放在独立的线程。

    修改配置后,并做了相关验证,如下图。

    验证的结论很遗憾,使用独立的线程来处理模型初始化并不能缓解毛刺问题。

    从而,进一步分析了 TF Serving 的线程机制,发现计算部分主要集中在 TF 的 Inter 和 Intra Op 线程,在模型初始化线程独立出来后,原来的推理请求基本不会被影响到。

    另外,经过分析还发现,TF 在执行 Restore Op 的时候会创建额外的线程池来恢复大的变量,于是尝试将 Restore 时的线程池去掉,发现仍然没有效果。

    内存原因分析

    先来看一下 TF 内存的分配机制,TF 的 GPU 显存是通过 BFC(best-fit with coalescing) 算法来分配的,CPU 内存分配是直接调用底层 glibc ptmalloc2 的 memory allocation。

    目前平台上 CTR 类业务基本都是 CPU 推理,因此内存的分配和释放都是通过 glibc ptmalloc2 来管理的。

    经过调研了解到,Linux glibc 的内存管理也是经过优化的,原来的实现是 dlmalloc,对多线程的支持并不好,现在的 ptmalloc2 是优化后支持了多线程。

    如果要深入到 ptmalloc2 优化内存管理就比较麻烦,不过调研发现已经有了开源的优化方案,那就是谷歌的 [Tcmalloc](http://goog-perftools.sourceforge.net/doc/tcmalloc.html) 和 Facebook 的 [Jemalloc](http://jemalloc.net/)。

    Ptmalloc,Tcmalloc 和 Jemalloc 的优缺点网上有很多分析的文章,都指出 Tcmalloc 和 Jemalloc 在多线程环境下有比较好的性能,大体从原理上来讲是区分大小内存块的分配,各个线程有自己内存分配区域,减少锁竞争。

    对比试验了三个内存分配器,实验结果如下图:

    从实验结果来看,Tcmalloc 和 Jemalloc 对毛刺都有比较好的缓解,但是 Tcmalloc 会增加正常情况下的 p999 延迟;而反观 Jemalloc 的毛刺 p999 降到了 50ms 以下,正常情况下的 p999 比 Ptmalloc也有所优化。

    看起来 Jemalloc 是一个相对比较理想的方案,不过在进一步的试验中发现,如果同时更新两个版本,Jemalloc 的 p999 毛刺会达到近 60ms,并且更新后会有一个比较长的延迟抖动期,会持续近一分钟时间,如下图:

    优化到这一步,如果对这样的延迟变化不敏感的话,基本就可以用 Jemalloc 来做为方案上线了,但对这样的效果仍觉得不是非常理想,因此进行了更深入的优化。

     问题的最终深入优化

    上面内存方案的优化效果提供了一个很好的启示和方向,毛刺的根本原因应该在内存的分配和释放竞争上,所以来进一步分析 TF 的内存分配。

    TF 内存分配和释放的使用场景主要分成两个部分:

    • 一部分是模型 Restore 时变量本身 Tensor 的分配,这个是在加载模型时分配的,内存的释放是在模型被卸载的时候

    • 一部分是 RPC 请求时网络前向计算时的中间输出Tensor 内存分配,在请求处理结束后就被释放

    模型更新时,新模型加载时的 Restore OP 有大量的内存被分配,旧模型被卸载时的有很多对象被析构,大量内存被释放。

    而这个过程中,RPC 请求没有中断,这个时候两者的内存分配和释放会产生冲突和竞争关系。

    因此设计了**内存分配隔离方案**

    将模型本身参数的内存分配和 RPC 请求过程中的内存分配隔离开来,让它们的分配和释放在不同的内存空间。

    结合模型的更新,线上模型一个容器里面最多就两个版本的模型文件,给每个模型版本各自分配了独立的内存池,用来做 AB 切换。

    在代码的编写上,TF 刚好有一个现成的 BFC 内存分配器,利用 BFC 做模型参数的内存分配器,RPC 请求的内存分配仍然使用 glibc ptmalloc2 来统一分配,因此最后的设计是这样:

    代码改动主要在 TF 的源码,主要是对 `ProcessState`,`ThreadPoolDevice` 和 `Allocator` 做了一些改动。

    最后来看一下试验效果:

    从图中,可以看到模型更新后,延迟抖动很少,大约在 2ms,在实际的线上测试高峰期大概有 5ms 的抖动,满足业务需求。

    总结

    本文介绍了爱奇艺深度学习平台对 TF Serving 毛刺问题的优化,主要归纳如下:

    1. 配置模型 Warmup 文件来初预热模型

    2. 使用 Jemalloc 做内存分配优化

    3. TF 模型参数分配和 RPC 请求内存分配分离

    经过实践,每个方法都有进一步的优化,最后基本解决了模型热更新过程中的毛刺问题。

    参考文献

    1. TF Serving Aarchtecture: https://github.com/tensorflow/serving/blob/master/tensorflow_serving/g3doc/architecture.md

    2. BVar: https://github.com/apache/incubator-brpc/blob/master/docs/cn/bvar.md

    3. TF WarmUp: https://www.tensorflow.org/tfx/serving/saved_model_warmup

    4. 美团基于 TensorFlow Serving 的深度学习在线预估: https://tech.meituan.com/2018/10/11/tfserving-improve.html

    5. Google Tcmalloc:http://goog-perftools.sourceforge.net/doc/tcmalloc.html

    6. Facebook Jemalloc: http://jemalloc.net/


    也许你还想看

    TensorFlow Ranking框架在海外推荐业务中的实践与应用

    基于TensorFlow Lite的移动端AR解决方案——SmileAR

    扫一扫下方二维码,更多精彩内容陪伴你!

    展开全文
  • 本文提到 CPU 统计和产生 core 文件的工具详见simple-perf-tools仓库。 问题描述 某服务所在机器统计显示,其 CPU 使用率在高峰时段出现毛刺。 暂时未收服务调用方的不良反馈。 初步排查 查看 CPU 1 分钟...
  • 本文排查一个Linux 机器 CPU 毛刺问题,排查过程不变更进程状态、也不会影响线上服务,最后还对 CPU 毛刺带来的风险进行了分析和验证。 本文提到 CPU 统计和产生 core 文件的工具详见 simple-perf-tools 仓库...
  • 摘要:我们在在线业务使用hbase读写数据时,可能会发现,HBase的平均延迟会很低,可能会低于1ms,但P999延迟(99.9%请求返回的最大时间)可能会高达数百ms。这就是所谓的"毛刺",这些毛刺可能会造成我们的在线业务...
  • 客户ADG环境,刚上线的业务系统,通过ZABBIX进行监控,发现每半个小时会出现ADG网卡流量超过1M,持续2分钟后,平均网络流量在100K左右。 二、分析 1、ADG 环境备库流量主要来自主库redo的数据传输,或者出现网络问题...
  • GLITCH.EXT是一个浏览器扩展程序,可以在网络上出现故障的网站! 这个扩展建立在同名net.art干预在 , 对于他们的 。 怎么了?! 这会在浏览时向网站注入3个库( , , )和, 使您能够在ANY *网站上干扰ANY *元素...
  • 由于同步设计依据统一时钟采样输入信号,因此输入信号之间的延迟,只要不大于时钟周期,系统就能保持正确的输出。由此可见采用同步设计避免了毛刺,保证了系统的稳定性。 二、周期period和最高频率fmax 上图...
  • 业务使用Netty发送消息,性能压测过程偶现一些消息发送耗时超过1S,采集了问题发生时CPU使用率,发现CPU占用率并不高,资源不是瓶颈。怀疑是代码BUG,相关性能统计代码如下所示: int sendBytes = ((ByteBuf)msg)...
  • 抖动 是指(业务)流量异常剧烈的波动,上下起伏大,例如下图: ... “毛刺”中文原意是指动物身上突出的尖刺,应用在Java就是指的(业务)流量上的突刺,如下图突出的两个蓝色流量, ...
  • 消息发送队列积压数可以反映网络速度、通信对端的读取速度、以及自身的发送速度等,因此对于服务调用时延的精细化分析对于问题定位非常有帮助,它的采集方式代码示例如下: publicvoid channelActive...
  • 为了降低采集过程各种噪声干扰以及老数据的磁带掉粉等因素造成的地震数据异常,处理与地层性质无关的抖动和毛刺干扰.采用时序RBF神经网络在线重构的方法.结果表明:在保留实际信息的前提下能有效的去除地震数据...
  • 可调节电流限制 低电流设计的灵活性 可调节软启动 允许控制开启坡道 热增强型QFN封装 改善散热 指定-40C至125C 应用 终端产品 服务器 网络 电信 ASICs servere 存储 网络 电路图、引脚图和封装图... 发表于 07-30 04...
  • 在DT我们模拟实际用户,不断地 上传或者下载不同大小的文件,通过测试软件的统计分析,获得网络性能的一些指标。 CQT(Call Quality Test)CQT原意是指拨打质量测试,在这里指固定的地点测试无线数据网络性能...
  • 背景 通过显微成像拍摄大脑非常薄的层的照片并以三维形式对其进行重构,可以确定结构在哪里以及它们之间的关系。但这会带来巨大挑战。获取高分辨率图像并快速...而且在串行块面电子显微镜的广泛使用的技术,将...
  • 版权声明:本书为作者版权所有,仅用于学习,请勿... OPENT网络仿真分析 (作者:栾鹏、陈玓玏) OPNET网络仿真分析-目录 OPNET网络仿真分析-电子版1.4、OPNET文件存储内容OPNET主要文件与对应记录内容如表1-11所示:
  • 因此对网络数据进行实时的精细化分析,能够发现毫秒级的网络毛刺并使之与应用相关联,有助于网络团队第一时间深入虚拟网络定位故障。通过网络数据分析系统进一步挖掘更大时间尺度上的网络风险,掌握网络运行的健康...
  • 三、综合布线施工应当注意的问题 由于网络综合布线工程实施设计对布线的全过程起着决定性的作用,工程实施的设计机构应慎之又慎。从整体上来说,在实施设计时首先应注意符合规范化标准。结构化布线的实施设计不仅...
  •  选择重传不是指分片的某个部分丢了,选择某个分片  选择重传的粒度不是分片而是滑动窗口的单元 TCP协议的seq表示的是字节数还是包序号?  seq其实就是连接的字节数 TCP发送数据后,基本就是已经异步过程...
  • 1数字电路设计的几个基本概念: 1.1 建立时间和保持时间:     图1建立时间和保持时间关系图 建立时间(setup time)是指在触发器的时钟信号上升沿到来以前,数据...
  • 一、可伸缩网络服务的设计与实现        人类社会正在进入以网络为中心的信息时代,人们需要更快捷、更可靠、功能更丰富的网络服务。万维网的流行促进互联网使用的指数级增长,...
  • PcapX射线 A Network Forensics Tool -... 给定一个Pcap文件,绘制一个网络图,显示网络中的主机,网络流量,突出显示重要流量和Tor流量以及潜在的恶意流量,包括通信涉及的数据。 问题: 鉴于最初的毛刺,对Pcap文
  • 布线质量决定了网络的运行质量,综合布线系统的测试可以实现问题的早发现、早改正,并为布线系统的认证提供可靠的质量数据。本文论述了电缆及光纤传输通道测试的技术问题。提出了用单端电缆测试仪等实现“随装随测”;...
  • 信号处理的卷积网络非线性计算猜想  本文根据深度学习的一些关键点对离散信号处理的算法进行了改进,以医疗信号的呼吸信号为例,估计其主要周期。下图为一片带有副波毛刺点的呼吸信号,已经较为强力的...
  • 本实用新型涉及计算机技术领域,具体为一种计算机网络设备用连接线。背景技术:计算机统称为电脑,是一种现代高速计算的电子计算机设备,同时可以数值计算和逻辑计算,同时具有存储记忆的功能,可以按照程序运行,其...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,877
精华内容 1,150
关键字:

网络中的毛刺