Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

端侧设备部署,onnx推理耗时20ms,是否正常以及还是否有优化手段 #37

Open
lhbing-ai opened this issue Sep 4, 2024 · 26 comments

Comments

@lhbing-ai
Copy link

cpu cotext-a7双核@1.2G
在端侧部署了实时流,单帧(16ms数据)推理耗时约20ms,也就是在这款设备上达不到实时流

1.当前设备20ms的推理时间是否正常
2.模型上还能否进一步裁剪的可能,业务上有没有优化的手段,比如输入的数据大一点,现在输入的是256的数据,也就是推理要小于16ms才有落地可能

@yuyun2000
Copy link

正常的,你这u确实有点弱

@xczhusuda
Copy link

可以试试MNN的框架

@lhbing-ai
Copy link
Author

可以试试MNN的框架

耗时改善不明显,基本也是在20ms左右,偶尔会快几ms,有波动;cpu上,你们一般用什么框架做推理?

@yuyun2000
Copy link

onnx

@TungyuYoung
Copy link

我在嵌入式平台上纯C写的推理,开了O3优化,5ms的推理速度。做完量化小于2ms。

@yuyun2000
Copy link

我在嵌入式平台上纯C写的推理,开了O3优化,5ms的推理速度。做完量化小于2ms。

什么U?

@TungyuYoung
Copy link

我在嵌入式平台上纯C写的推理,开了O3优化,5ms的推理速度。做完量化小于2ms。

什么U?

国产平台,主频1.2GHz左右,跑起来的时候占用是低于5%的。

@yuyun2000
Copy link

太强了

@lhbing-ai
Copy link
Author

我在嵌入式平台上纯C写的推理,开了O3优化,5ms的推理速度。做完量化小于2ms。

什么U?

国产平台,主频1.2GHz左右,跑起来的时候占用是低于5%的。

写的C推理,有多大的工作量,性能太强了

@TrilSiaWalt
Copy link

我在嵌入式平台上纯C写的推理,开了O3优化,5ms的推理速度。做完量化小于2ms。

你好大佬 请问可以咨询一下技术细节吗?我给您发了邮件

@hfwanguanghui
Copy link

分组GRU部分和双向GRU耗时大,需要减小一个,并且改成单向GRU,重新训练模型,推理耗时才会降下来。

@TungyuYoung
Copy link

分组GRU部分和双向GRU耗时大,需要减小一个,并且改成单向GRU,重新训练模型,推理耗时才会降下来。

事实上ConvTranspose在我这里耗时是最大的。不知道有什么方法可以进一步优化。

@songdaw
Copy link

songdaw commented Sep 25, 2024

分组GRU部分和双向GRU耗时大,需要减小一个,并且改成单向GRU,重新训练模型,推理耗时才会降下来。

事实上ConvTranspose在我这里耗时是最大的。不知道有什么方法可以进一步优化。

我也是直接实现的ConvTranspose很慢,改成插值+Conv实现后效率高不少。

@yuyun2000
Copy link

改完岂不是还要重新训练?

@TungyuYoung
Copy link

分组GRU部分和双向GRU耗时大,需要减小一个,并且改成单向GRU,重新训练模型,推理耗时才会降下来。

事实上ConvTranspose在我这里耗时是最大的。不知道有什么方法可以进一步优化。

我也是直接实现的ConvTranspose很慢,改成插值+Conv实现后效率高不少。

用插值会影响效果吗?另外请问有没有什么参考的代码来实现您所提到的?

@songdaw
Copy link

songdaw commented Sep 29, 2024

ConvTranspose和插值+Conv是等价操作,结果是一样的,当然需要Conv本身优化好的情况下才有效果,具体可以看看文章"A guide to convolution arithmetic for deep learning"

@Xiaobin-Rong
Copy link
Owner

感谢反馈,一开始也试过使用Conv来实现流式的Contranspose,后来嫌麻烦直接弃用了,没想到会有效率的问题。这里是之前的代码可供参考:

class StreamConvTranspose2d(nn.Module):
    def __init__(self, 
                 in_channels: int,
                 out_channels: int,
                 kernel_size: Union[int, Tuple[int, int]],
                 stride: Union[int, Tuple[int, int]] = 1,
                 padding: Union[str, int, Tuple[int, int]] = 0,
                 dilation: Union[int, Tuple[int, int]] = 1,
                 groups: int = 1,
                 bias: bool = True,
                 *args, **kargs):
        super().__init__(*args, **kargs)
        """
        流式转置卷积实现。
        默认 kernel_size = [T_size, F_size]
        默认 stride = [T_stride, F_stride] 且 T_stride == 1
        """
        self.in_channels = in_channels
        self.out_channels = out_channels
        if type(kernel_size) is int:
            self.T_size = kernel_size
            self.F_size = kernel_size
        elif type(kernel_size) in [list, tuple]:
            self.T_size, self.F_size = kernel_size
        else:
            raise ValueError('Invalid kernel size.')
            
        if type(stride) is int:
            self.T_stride = stride
            self.F_stride = stride
        elif type(stride) in [list, tuple]:
            self.T_stride, self.F_stride = stride
        else:
            raise ValueError('Invalid stride size.')
        
        assert self.T_stride == 1

        if type(padding) is int:
            self.T_pad = padding
            self.F_pad = padding
        elif type(padding) in [list, tuple]:
            self.T_pad, self.F_pad = padding
        else:
            raise ValueError('Invalid padding size.')
        assert(self.T_pad == 0) 

        if type(dilation) is int:
            self.T_dilation = dilation
            self.F_dilation = dilation
        elif type(dilation) in [list, tuple]:
            self.T_dilation, self.F_dilation = dilation
        else:
            raise ValueError('Invalid dilation size.')
        
        # 我们使用权重时间反向的Conv2d实现转置卷积    
        self.ConvTranspose2d = nn.Conv2d(in_channels = in_channels, 
                                        out_channels = out_channels,
                                        kernel_size = kernel_size,
                                        stride = (self.T_stride, 1), # 若F维度stride不为1,将在forward中使用额外的上采样算子
                                        padding = (self.T_pad, 0),   # 若F维度padding不为0,将在forward中使用额外的填充
                                        dilation = dilation,
                                        groups = groups,
                                        bias = bias)
        
    def forward(self, x, cache):
        """
        x: [bs,C,1,F]
        cache: [bs,C,T-1,F]
        """
        # [bs,C,T,F]
        inp = torch.cat([cache, x], dim = 2)
        out_cache = inp[:, :, 1:]
        bs, C, T, F = inp.shape
        #添加上采样算子
        if self.F_stride > 1: 
            # [bs,C,T,F] -> [bs,C,T,F,1] -> [bs,C,T,F,F_stride] -> [bs,C,T,F_out]
            inp = torch.cat([inp[:,:,:,:,None], torch.zeros([bs,C,T,F,self.F_stride-1])], dim = -1).reshape([bs,C,T,-1])
            left_pad = self.F_stride - 1
            if self.F_size > 1:
                if left_pad <= self.F_size - 1:
                    inp = torch.nn.functional.pad(inp, pad = [(self.F_size - 1)*self.F_dilation-self.F_pad, (self.F_size - 1)*self.F_dilation-self.F_pad - left_pad, 0, 0])
                else:
                    # inp = torch.nn.functional.pad(inp, pad = [self.F_size - 1, 0, 0, 0])[:,:,:,: - (left_pad - self.F_stride + 1)]
                    raise(NotImplementedError)
            else:
                # inp = inp[:,:,:,:-left_pad]
                raise(NotImplementedError)

        else: # F_stride = 1
            inp = torch.nn.functional.pad(inp, pad=[(self.F_size-1)*self.F_dilation-self.F_pad, (self.F_size-1)*self.F_dilation-self.F_pad])
                
        outp = self.ConvTranspose2d(inp)
    
        return outp, out_cache

代码的实现可能不太完善,如有错误的地方欢迎指出~

@maoyapeng
Copy link

maoyapeng commented Oct 12, 2024

我在嵌入式平台上纯C写的推理,开了O3优化,5ms的推理速度。做完量化小于2ms。

什么U?

国产平台,主频1.2GHz左右,跑起来的时候占用是低于5%的。

太强了,我做完量化后,采用的芯片npu推理,16ms音频大概需要3ms,跑起来大概20%。
但是在实时用的时候,有些女声声音,做完后会偶尔抑制,听感上有电音感。

@HuixiangH
Copy link

分组GRU部分和双向GRU耗时大,需要减小一个,并且改成单向GRU,重新训练模型,推理耗时才会降下来。

分组GRU部分的耗时大这个结论是相对于普通GRU还是Conv来说的呢?
如果是相对于GRU来说,理论上分组后计算量和参数量都是减半的。即使考虑访存的效率,分组GRU的特征分割和特征组合(这边的gGRU没有做shuffle),都是对两个连续内存的操作,也都是很快的。

@SEMLLYCAT
Copy link

我在嵌入式平台上纯C写的推理,开了O3优化,5ms的推理速度。做完量化小于2ms。

什么U?

国产平台,主频1.2GHz左右,跑起来的时候占用是低于5%的。

太强了,我做完量化后,采用的芯片npu推理,16ms音频大概需要3ms,跑起来大概20%。 但是在实时用的时候,有些女声声音,做完后会偶尔抑制,听感上有电音感。

太强了,请问量化后精度损失多少

@maoyapeng
Copy link

我在嵌入式平台上纯C写的推理,开了O3优化,5ms的推理速度。做完量化小于2ms。

什么U?

国产平台,主频1.2GHz左右,跑起来的时候占用是低于5%的。

太强了,我做完量化后,采用的芯片npu推理,16ms音频大概需要3ms,跑起来大概20%。 但是在实时用的时候,有些女声声音,做完后会偶尔抑制,听感上有电音感。

太强了,请问量化后精度损失多少

524ee738db9d98a07ed7b5a5f9c8683
基本看不出有明显精度损失

@yuyun2000
Copy link

我在嵌入式平台上纯C写的推理,开了O3优化,5ms的推理速度。做完量化小于2ms。

什么U?

国产平台,主频1.2GHz左右,跑起来的时候占用是低于5%的。

太强了,我做完量化后,采用的芯片npu推理,16ms音频大概需要3ms,跑起来大概20%。 但是在实时用的时候,有些女声声音,做完后会偶尔抑制,听感上有电音感。

太强了,请问量化后精度损失多少

524ee738db9d98a07ed7b5a5f9c8683 基本看不出有明显精度损失

请问是fp16还是int8?

@maoyapeng
Copy link

我在嵌入式平台上纯C写的推理,开了O3优化,5ms的推理速度。做完量化小于2ms。

什么U?

国产平台,主频1.2GHz左右,跑起来的时候占用是低于5%的。

太强了,我做完量化后,采用的芯片npu推理,16ms音频大概需要3ms,跑起来大概20%。 但是在实时用的时候,有些女声声音,做完后会偶尔抑制,听感上有电音感。

太强了,请问量化后精度损失多少

524ee738db9d98a07ed7b5a5f9c8683 基本看不出有明显精度损失

请问是fp16还是int8?

int16

@lhbing-ai
Copy link
Author

我在嵌入式平台上纯C写的推理,开了O3优化,5ms的推理速度。做完量化小于2ms。

什么U?

国产平台,主频1.2GHz左右,跑起来的时候占用是低于5%的。

太强了,我做完量化后,采用的芯片npu推理,16ms音频大概需要3ms,跑起来大概20%。 但是在实时用的时候,有些女声声音,做完后会偶尔抑制,听感上有电音感。

太强了,请问量化后精度损失多少

524ee738db9d98a07ed7b5a5f9c8683 基本看不出有明显精度损失

请问是fp16还是int8?

int16

  1. 请问下 用的什么芯片平台可以支持gtcrn模型的量化,npu算力多少? 3ms应该是能实时用了。
  2. 另外大家有没有发现,整段音频做推理和实时流单帧推理得到的结果会存在2%左右的差异(实时流推理,怀疑和gru实时更新有关),这个误差是否是客观存在的?

@maoyapeng
Copy link

我在嵌入式平台上纯C写的推理,开了O3优化,5ms的推理速度。做完量化小于2ms。

什么U?

国产平台,主频1.2GHz左右,跑起来的时候占用是低于5%的。

太强了,我做完量化后,采用的芯片npu推理,16ms音频大概需要3ms,跑起来大概20%。 但是在实时用的时候,有些女声声音,做完后会偶尔抑制,听感上有电音感。

太强了,请问量化后精度损失多少

524ee738db9d98a07ed7b5a5f9c8683 基本看不出有明显精度损失

请问是fp16还是int8?

int16

  1. 请问下 用的什么芯片平台可以支持gtcrn模型的量化,npu算力多少? 3ms应该是能实时用了。
  2. 另外大家有没有发现,整段音频做推理和实时流单帧推理得到的结果会存在2%左右的差异(实时流推理,怀疑和gru实时更新有关),这个误差是否是客观存在的?

ssc的一款,0.4T。实时用没问题

@xczhusuda
Copy link

感谢反馈,一开始也试过使用Conv来实现流式的Contranspose,后来嫌麻烦直接弃用了,没想到会有效率的问题。这里是之前的代码可供参考:

class StreamConvTranspose2d(nn.Module):
    def __init__(self, 
                 in_channels: int,
                 out_channels: int,
                 kernel_size: Union[int, Tuple[int, int]],
                 stride: Union[int, Tuple[int, int]] = 1,
                 padding: Union[str, int, Tuple[int, int]] = 0,
                 dilation: Union[int, Tuple[int, int]] = 1,
                 groups: int = 1,
                 bias: bool = True,
                 *args, **kargs):
        super().__init__(*args, **kargs)
        """
        流式转置卷积实现。
        默认 kernel_size = [T_size, F_size]
        默认 stride = [T_stride, F_stride] 且 T_stride == 1
        """
        self.in_channels = in_channels
        self.out_channels = out_channels
        if type(kernel_size) is int:
            self.T_size = kernel_size
            self.F_size = kernel_size
        elif type(kernel_size) in [list, tuple]:
            self.T_size, self.F_size = kernel_size
        else:
            raise ValueError('Invalid kernel size.')
            
        if type(stride) is int:
            self.T_stride = stride
            self.F_stride = stride
        elif type(stride) in [list, tuple]:
            self.T_stride, self.F_stride = stride
        else:
            raise ValueError('Invalid stride size.')
        
        assert self.T_stride == 1

        if type(padding) is int:
            self.T_pad = padding
            self.F_pad = padding
        elif type(padding) in [list, tuple]:
            self.T_pad, self.F_pad = padding
        else:
            raise ValueError('Invalid padding size.')
        assert(self.T_pad == 0) 

        if type(dilation) is int:
            self.T_dilation = dilation
            self.F_dilation = dilation
        elif type(dilation) in [list, tuple]:
            self.T_dilation, self.F_dilation = dilation
        else:
            raise ValueError('Invalid dilation size.')
        
        # 我们使用权重时间反向的Conv2d实现转置卷积    
        self.ConvTranspose2d = nn.Conv2d(in_channels = in_channels, 
                                        out_channels = out_channels,
                                        kernel_size = kernel_size,
                                        stride = (self.T_stride, 1), # 若F维度stride不为1,将在forward中使用额外的上采样算子
                                        padding = (self.T_pad, 0),   # 若F维度padding不为0,将在forward中使用额外的填充
                                        dilation = dilation,
                                        groups = groups,
                                        bias = bias)
        
    def forward(self, x, cache):
        """
        x: [bs,C,1,F]
        cache: [bs,C,T-1,F]
        """
        # [bs,C,T,F]
        inp = torch.cat([cache, x], dim = 2)
        out_cache = inp[:, :, 1:]
        bs, C, T, F = inp.shape
        #添加上采样算子
        if self.F_stride > 1: 
            # [bs,C,T,F] -> [bs,C,T,F,1] -> [bs,C,T,F,F_stride] -> [bs,C,T,F_out]
            inp = torch.cat([inp[:,:,:,:,None], torch.zeros([bs,C,T,F,self.F_stride-1])], dim = -1).reshape([bs,C,T,-1])
            left_pad = self.F_stride - 1
            if self.F_size > 1:
                if left_pad <= self.F_size - 1:
                    inp = torch.nn.functional.pad(inp, pad = [(self.F_size - 1)*self.F_dilation-self.F_pad, (self.F_size - 1)*self.F_dilation-self.F_pad - left_pad, 0, 0])
                else:
                    # inp = torch.nn.functional.pad(inp, pad = [self.F_size - 1, 0, 0, 0])[:,:,:,: - (left_pad - self.F_stride + 1)]
                    raise(NotImplementedError)
            else:
                # inp = inp[:,:,:,:-left_pad]
                raise(NotImplementedError)

        else: # F_stride = 1
            inp = torch.nn.functional.pad(inp, pad=[(self.F_size-1)*self.F_dilation-self.F_pad, (self.F_size-1)*self.F_dilation-self.F_pad])
                
        outp = self.ConvTranspose2d(inp)
    
        return outp, out_cache

代码的实现可能不太完善,如有错误的地方欢迎指出~

(py310torch201) r python convert_onnx_mnn.py
Traceback (most recent call last):
File "/home//speech_enhancement/se_train/speech_enhancement/runners/ns/model/monaural/GTCRN/flow_infer/oonx_model_mnn/convert_onnx_mnn.py", line 70, in
stream_model = StreamGTCRN().to(device).eval()
File "/home/
/speech_enhancement/se_train/speech_enhancement/runners/ns/model/monaural/GTCRN/flow_infer/model_stream/gtcrn_stream.py", line 317, in init
self.decoder = StreamDecoder()
File "/home//speech_enhancement/se_train/speech_enhancement/runners/ns/model/monaural/GTCRN/flow_infer/model_stream/gtcrn_stream.py", line 272, in init
StreamGTConvBlock(16, 16, (3,3), stride=(1,1), padding=(2
5,1), dilation=(5,1), use_deconv=True),
File "/home/
/speech_enhancement/se_train/speech_enhancement/runners/ns/model/monaural/GTCRN/flow_infer/model_stream/gtcrn_stream.py", line 125, in init
self.depth_conv = stream_conv_module(hidden_channels, hidden_channels, kernel_size,
File "/home/
**/speech_enhancement/se_train/speech_enhancement/runners/ns/model/monaural/GTCRN/flow_infer/modules/convolution.py", line 141, in init
assert(self.T_pad == 0)
AssertionError

您好,这边遇到了报错问题

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests