欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 运维知识 > linux >内容正文

linux

让kaldi在Linux开发板上运行起来~ (测试运行篇)

发布时间:2023/12/8 linux 43 豆豆
生活随笔 收集整理的这篇文章主要介绍了 让kaldi在Linux开发板上运行起来~ (测试运行篇) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

【kaldi各文件解释】

  • /egs:不同语料例子的执行脚本文件

  • /tools:存放asr过程中用到的库

  • /src:存放实际执行的c++算法

  • 解码工具(src/onlinebin中):

    online-gmm-decode-faster:识别从麦克风输入的语音

    online-wav-gmm-decode-faster:识别指定的wav文件

【分析chain模型的目录结构】

run.sh根据wavpath生成的数据关系保存在/data里,文件解释如下:

  • spk2utt 包含说话人编号和说话人的语音编号的信息
  • utt2spk 语音编号和说话人编号之间的关系
  • wav.scp 包含了原始语音的路径信息(格式:文件名 路径)

{local, steps, utils}里面包含了run.sh所要用到各种的脚本文件


【运行数据堂chain模型】

将数据堂训练好的模型移动到kaldi/egs的后续准备工作:

①Go to kaldi/egs/aidatatang_asr, create symlinks to /steps/ and /utils/ like this:

ln -s ../wsj/s5/steps/ steps ln -s ../wsj/s5/utils/ utils

②设置你自己的WAVPATH

③运行模型:./run.sh WAVpath


但事情往往没那么简单。。。

【run.sh运行过程】

报错1:

需要移植python,perl。

用buildroot配置,target packages->Interpreter languages and scripting->选中python和perl

sudo make时报错

将文件复制到设备:__populate_fs: 无法为ext2文件系统分配块 写入文件“modules.symbols.bin”时 mkfs.ext4: 无法为ext2文件系统分配块 于填充文件系统时 *** Maybe you need to increase the filesystem size (BR2_TARGET_ROOTFS_EXT2_SIZE)

解决:sudo vim .config,调整BR2_TARGET_ROOTFS_EXT2_SIZE为100M


报错2:

解决:去掉.decode('utf8')

报错3:

local/decode.sh exp/chain/tdnn_1a_sp exp/chain/tdnn_1a_sp/decode_offline_test_19700101 8 utils/copy_data_dir.sh: copied data from data/offline_test to data/offline_test_hires mktemp: Invalid argument sort: invalid option -- 'C' BusyBox v1.29.3 (2020-12-01 11:02:45 CST) multi-call binary.Usage: sort [-nrugMcszbdfiokt] [-o FILE] [-k start[.offset][opts][,end[.offset][opts]] [-t CHAR] [FILE]...Sort lines of text-o FILE Output to FILE-c Check whether input is sorted-b Ignore leading blanks-f Ignore case-i Ignore unprintable characters-d Dictionary order (blank or alphanumeric only)-n Sort numbers-g General numerical sort-M Sort month-t CHAR Field separator-k N[,M] Sort by Nth field-r Reverse sort order-s Stable (don't sort ties alphabetically)-u Suppress duplicate lines-z Lines are terminated by NUL, not newline utils/validate_data_dir.sh: file data/offline_test_hires/utt2spk is not sorted or has duplicates

查找包含mktemp的文件:grep -rn "mktemp" *

根据上面的结果追踪:decode.sh → utils/copy_data_dir.sh → utils/validate_data_dir.sh

tmpdir=$(mktemp -d /tmp/kaldi.XXXX);

根源:脚本是gnu版本的mktemp,而它与busybox版本的mktemp用法不同。

gnu linux核心命令和工具的源码路径

mktemp源码:ftp://ftp.mktemp.org/pub/mktemp

结果:交叉编译后在板子上正常运行!

还需要解决sort错误:


【更换coreutils】

​ 大部分人的工作环境基本都是GNU/Linux,而我们的开发板中的工作组件(busybox-coreutils),与gnu的核心工具组件有一部分是不太兼容的,如mktemp

#mktemp --help in busybox Create a temporary file with name based on TEMPLATE and print its name. TEMPLATE must end with XXXXXX (e.g. [/dir/]nameXXXXXX). Without TEMPLATE, -t tmp.XXXXXX is assumed.#mktemp --help in gnu Create a temporary file or directory, safely, and print its name. TEMPLATE must contain at least 3 consecutive `X's in last component. If TEMPLATE is not specified, use tmp.XXXXXXXXXX, and --tmpdir is implied.

诸如mv,sort等命令在gnu和busybox的实现多少是有些差别的。

而因为我们要想在开发板上(移植)运行一些开源软件,就需要重新交叉编译一下移植gnu的coreutils。

手动编译:gnu-coreutils源码下载地址:https://ftp.gnu.org/gnu/coreutils/

buildroot配置coreutils:target packages → systemtool → coreutils



报错4:

执行decode.sh时莫名其妙就aborted了。。。

卡在解码!!!


手动运行解码命令:

export TRAINDIR=exp/chain/tdnn_1a_sp export GRAPHDIR=exp/chain/tdnn_1a_sp/graph./steps/online/nnet3/prepare_online_decoding.sh $GRAPHDIR $TRAINDIR ./chain_conf #生成一些配置文件 /root/kaldi/src/online2bin/online2-wav-nnet3-latgen-faster --do-endpointing=false --frames-per-chunk=20 --extra-left-context-initial=0 --online=true --config=chain_conf/conf/online.conf --min-active=200 --max-active=7000 --beam=15.0 --lattice-beam=6.0 --acoustic-scale=1.0 --word-symbol-table=$GRAPHDIR/words.txt $TRAINDIR/final.mdl $GRAPHDIR/HCLG.fst --utt2spk=ark:data/offline_test_hires/split4/1/utt2spk 'ark,s,cs:wav-copy scp,p:data/offline_test_hires/split4/1/wav.scp ark:- |' 'ark:|lattice-scale --acoustic-scale=10.0 ark:- ark:- | gzip -c >exp/chain/tdnn_1a_sp/decode_offline_test_19700101/lat.1.gz'

报错:

what(): std::bad_alloc经查找资源,好像是内存不够了,(别好像,就是内存不够)。


还尝试过修改源码(意义不大):

结合提示信息与nnet-compile-looped.cc上下文中的提示输出,可以定位到

for (num_requests = num_requests1; num_requests <= max_requests;num_requests *= factor) {if (CompileLoopedInternal(nnet, optimize_opts,request1, request2, request3,num_requests, computation)) {KALDI_LOG << "Spent " << timer.Elapsed()<< " seconds in looped compilation.";return;} }}

应该是for循环中内存耗尽。再看CompileLoopedInternal函数

std::vector extra_requests

修改:在CompileLoopedInternal函数结尾添加vector().swap(extra_requests); 手动清除vector空间。

意义不大。。。


#### 编译valgrind,查看内存使用情况,是否有泄漏:

buildroot → target packages → debugging… 中有valgrind选项,但下载很慢。不过手动下载也不快,然后编译也有不少问题,建议用buildroot直接配置。

下载地址:http://valgrind.org

手动编译:

#!/bin/bashCXX=arm-linux-gnueabihf-g++ CC=arm-linux-gnueabihf-gcc ./configure --prefix= --host=arm-linux-gnueabihf make -j4 make install DESTDIR=`pwd`/build

开发板中测试,valgrind --tool=memcheck --leak-check=full ./onlinewav.sh

==554== HEAP SUMMARY: ==554== in use at exit: 26,382 bytes in 540 blocks ==554== total heap usage: 999 allocs, 459 frees, 51,831 bytes allocated ==554== ==554== 594 bytes in 33 blocks are still reachable in loss record 1 of 4 ==554== at 0x483D858: malloc (vg_replace_malloc.c:307) ==554== by 0x6DC4B: initialize_signames (in /bin/bash) ==554== ==554== 1,614 bytes in 4 blocks are still reachable in loss record 2 of 4 ==554== at 0x483D858: malloc (vg_replace_malloc.c:307) ==554== by 0x6DAD7: xrealloc (in /bin/bash) ==554== ==554== 1,657 bytes in 4 blocks are still reachable in loss record 3 of 4 ==554== at 0x4840550: realloc (vg_replace_malloc.c:834) ==554== by 0x6DACB: xrealloc (in /bin/bash) ==554== ==554== 22,517 bytes in 499 blocks are still reachable in loss record 4 of 4 ==554== at 0x483D858: malloc (vg_replace_malloc.c:307) ==554== by 0x6DA8F: xmalloc (in /bin/bash) ==554== ==554== LEAK SUMMARY: ==554== definitely lost: 0 bytes in 0 blocks ==554== indirectly lost: 0 bytes in 0 blocks ==554== possibly lost: 0 bytes in 0 blocks ==554== still reachable: 26,382 bytes in 540 blocks ==554== suppressed: 0 bytes in 0 blocks ==554== ==554== For lists of detected and suppressed errors, rerun with: -s ==554== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

没有什么发现。。。(kaldi有那么多大神在维护,源码上应该没问题的,更何况是内存泄露这种严重的问题。)



将整个文件系统烧到128G SD卡中:

​ 本以为这会儿应该能解决了,但,,,,磁盘==内存?

我的天,plan-lastest(基本是最后的测试方案了),行不通。。。。。。。

上网查std::bad_alloc是怎么回事,在github中看到一个dan神的回复:https://github.com/kaldi-asr/kaldi/issues/3977,建议用gdb调试。


尝试用gdb调试,定位错误:

https://jason–liu.github.io/2018/01/23/gdbdebug/

【gdb调试时函数都是“?”】

猜测:交叉编译环境下和开发板运行环境中调用的lib.so.6不一样。实际用diff命令检查时,发现还真不一样。

修改kaldi.mk

删除src/nnet3和src/nnet3bin下的目标文件(*.o)

重新编译链接:make

现实是残酷的:还是存在问号。

【实际原因】:注意info sharedlibrary时报的错误(*): Shared library is missing debugging information.

动态库缺少debug 信息,但这影响的仅仅是gdb调试过程,而对kaldi实际运行过程没有影响。先跳过。


【尝试添加虚拟内存】:

尝试了很多种方法,但好像都有点问题,如

①直接NFS时创建swap文件,报swapfile has holes;

②在进入sd卡文件系统后,fdisk /dev/mmcblk0p2,对分区2(根文件系统的挂载分区)再分区,但doesn’t contain a valid partition table,fdisk命令后无法w,不起作用。也试过在虚拟机下对/dev/sdd2分区,行不通。

③sd卡下创建swap文件,运行时报mmcblk0: retrying using single block read,error:-84…

​ 最后,在某一天晚上,在解决gdb问句和swap分区不起作用问题,都没有建树后,打算睡觉来着。但想了想再看一下,整理一下虚拟机环境(解决问号问题时尝试移植glibc库,版本不对,根文件系统直接崩溃了,还把lib目录搞的有点乱)


正文!!!:

​ 然后又试了下运行kaldi解码,就那一刻突然开窍了,注意到了一个细节,③中:在解码时,报错会晚一点点,猜测是在尝试使用虚拟内存时报的错。说明什么?说明使用虚拟内存使得程序的崩溃点推迟了,根本原因就是运行内存不足!

​ 重新分析添加虚拟内存时出现的问题,在尝试③中有了突破,mmcblk0: retrying using single block read,error:-84…的问题在于SD卡的读写速度太快,应该要修改一下sd卡的时钟频率。SD卡中swap文件虽然可以作为虚拟内存,但与实际内存的读写速度是不一样的。

​ 于是我想到好像可以去dts中修改usdhc的时钟配置。而在这时突然灵光一闪,sd卡速度太快?emmc作为开发板上的默认储存器,与CPU的读写应该适配吧。然后就尝试用emmc作为虚拟内存。

mkswap /dev/mmcblk1p2 swapon /dev/mmcblk1p2 cat /proc/swap //查看交换区是否被成功启用。

重新运行kaldi,终于没报aborted或bad_alloc()了。


import zlib问题:

ModuleNotFoundError,没有找到zlib库,import zlib失败

先到steps/nnet3/decode.sh中,将stage修改为2。因为steps/nnet3/decode.sh: feature type is raw这一步花费时间实在太长了,而且在第一次测试时通过了,所以直接可以跳过。方便后面的调试。(所有步骤测试都完成后记得改回去。)


Buildroot配置python:

​ Target packages --》 Interpreter languages and scripting --》python

(之前配置为python3.7时,使能zlib module无效;现在换成python2.7,能成功通过import zlib)

创建一个test.py:

import zlib print "import zlib ok."

python test.py,能正常打印说明配置成功。

结果还是要python3.7的zlib的模块,不能直接将python2中的zlib.so拷贝。

File "usr/lib/python3.7/gzip.py", line 9, in <module> ImportError: dynamic module does not define module export function (PyInit_zlib)

怎么将python3.7编译出zlib.so链接库???

在output/build/python3.7中的Makefile和configure修改了半天,但每次重新编译buildroot时却没有反应?

buildroot重新编译问题:

解决:修改Makefile或configure后,还要将.stamp_configured或.stamp_built等删除,再重新编译buildroot。

成功解决import zlib问题。


再次运行run.sh

测试成功,不过运行要3分钟左右,也为难开发板了,只有512MB DDR3,792MHz 主频。其中的数字和字母的组合好像没识别出来,可以尝试使用其它模型(推荐CVTE的模型,正确率高达92%)或自己训练模型。

因为IMX6ULL的性能远不如树莓派4,且在其它嵌入式平台上配置不如在raspbian上方便,故而在运行时会出很多其它问题。


总结:Imx6ull的性能导致其解码识别的速度很慢,所以要实际应用到项目用,需要换更高配一些的芯片。

总结

以上是生活随笔为你收集整理的让kaldi在Linux开发板上运行起来~ (测试运行篇)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。