Xiaobin-Rong / gtcrn

The official implementation of GTCRN, an ultra-lite speech enhancement model.
MIT License
219 stars 37 forks source link

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

Open lhbing-ai opened 2 months ago

lhbing-ai commented 2 months ago

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

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

yuyun2000 commented 2 months ago

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

xczhusuda commented 2 months ago

可以试试MNN的框架

lhbing-ai commented 2 months ago

可以试试MNN的框架

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

yuyun2000 commented 2 months ago

onnx

TungyuYoung commented 2 months ago

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

yuyun2000 commented 2 months ago

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

什么U?

TungyuYoung commented 2 months ago

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

什么U?

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

yuyun2000 commented 2 months ago

太强了

lhbing-ai commented 2 months ago

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

什么U?

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

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

TrilSiaWalt commented 2 months ago

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

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

hfwanguanghui commented 2 months ago

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

TungyuYoung commented 2 months ago

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

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

songdaw commented 2 months ago

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

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

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

yuyun2000 commented 2 months ago

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

TungyuYoung commented 2 months ago

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

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

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

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

songdaw commented 1 month ago

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

Xiaobin-Rong commented 1 month ago

感谢反馈,一开始也试过使用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 commented 1 month ago

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

什么U?

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

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

HuixiangH commented 1 month ago

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

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

SEMLLYCAT commented 1 month ago

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

什么U?

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

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

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

maoyapeng commented 1 month ago

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

什么U?

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

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

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

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

yuyun2000 commented 1 month ago

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

什么U?

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

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

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

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

请问是fp16还是int8?

maoyapeng commented 1 month ago

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

什么U?

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

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

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

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

请问是fp16还是int8?

int16

lhbing-ai commented 1 month ago

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

什么U?

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

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

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

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

请问是fp16还是int8?

int16

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

我在嵌入式平台上纯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。实时用没问题