一种基于lib库的Difar算法高效移植方法
2022-08-25徐丞君
徐丞君
中国船舶第七一五研究所,浙江杭州 310012
0 前言
被动定向声纳浮标是海军反潜巡逻机[1]常用的一种搜索发现定位水下移动目标的武器设备,其具有作用距离远、性价比高、隐蔽性强、部署灵活等优点。被动定向声纳浮标水听器具有方向性[2],可以将被动接受到的水下目标信息进行耦合,使其包含全向信息与方向信息,随后通过DSP板将得到的信息经过被动定向声纳浮标(Difar)算法计算即解复用以及互谱法,还原出目标的频谱与方位信息,从而发现水下潜藏的目标及方位。
在海军制式装备中,被动定向声纳浮标算法一般运行在DSP(Digital Signal Processing)板上。但是DSP板的价格高、开发周期长[3],而且调试运行代码也不易。一套运行于DSP板的Difar算法系统设备少则几十万,如此高昂的价格会严重影响模拟实验训练、数据回放需求方的采购数量,而PC平台价格实惠,一台几万的设备就可以达到相应的算力,同时由于在模拟实验训练、数据回放等情况下不会出现极端环境造成PC平台宕机等问题,所以,如何在PC平台搭建Difar算法处理系统是一个具有现实经济意义的任务。本文着重研究了一种基于lib库文件形式,即将底层函数通过宏定义隔离生成lib库文件的方式,高效地实现了Difar算法从DSP板到PC平台的移植。
1 算法原理[4]
被动定向浮标水听器包含两部分:一部分是全向水听器,可以得到全向信号;另一部分是两个正交的偶极子传感器沿着浮标的X轴与Y轴方向进行布置,对应于X信号,Y信号。不失一般性,假设目标频率为Freq的单频信号,目标与Y正轴夹角为θ,则全向、东西、南北信号分别为:
其中,Omi——全向信号;
Freq——目标频率;
t——时间。
其中,EW——X信号,即东西信号;
θ——目标与Y正轴夹角。
其中,NS——Y信号,即南北信号。
假设,导相频率为φ,导频频率为φ/2,地理正北方向与Y轴正轴夹角为σ,则复合以后的信号为:
其中,sig——复合后的信号;
φ——导相频率;
σ——地理正北方向与Y轴正轴夹角。
当DSP信号处理板接收到复合信号以后就进行Difar算法运行,即先将复合信号经过解复用,还原出原先的全向信号与东西信号、南北信号;接着通过互谱法得到目标频率与方位,即假设求得的全向、东西、南北信号对应的频率为FO(m),FEW(m),FNS(m),则全向与东西信号互功率谱为:
IEW——全向与东西信号频率互谱求解后的结果。同理,全向与南北信号互功率谱为:
INS——全向与南北信号频率互谱求解后的结果。则目标的方位与频率之间关系为:
其中,ϑ——INS(m)与IEW(m)之比的正切角。
Difar算法的程序框图如图1所示。首先,Difar算法需要先将被动定向浮标耦合得到的复合信号进行解复用,得到全向、东西、南北信号,然后进行互谱法,最后得到频率与方位信息。
2 lib库设计思路
在将上一节的Difar算法用C语言实现过程中,会涉及到诸如FFT、数组拷贝、数学函数等接口的使用,而在Win系统VS开发环境与DSP如Ti6678板开发环境中,这些函数的接口调用方式是不同的。如数据搬移函数,在Ti6678开发环境下,包含两种函数:
(1)void DSP_blk_mov_cn(const short* restrict x, short *restrict r, int nx)
(2)void DSP_blk_move(short* restrict x, short *restrict r, int nx)
此两个函数的使用区别为:当nx>= 8; nx %8 =0时,采用DSP_blk_move函数;否则采用DSP_blk_mov_cn函数。但是,在Win系统VS开发环境中,数据搬移函数[5]的声明如下:
void* __cdeclmemcpy(
_Out_writes_bytes_all_(_Size) void* _Dst,
_In_reads_bytes_(_Size) void const* _Src,
_In_ size_t _Size
);
可见,此两种平台同一种功能的函数接口的形式完全不同。如果在Difar算法实现过程中直接调用相应平台的接口函数的话,那么在移植过程中,会给程序员造成非常大的工作量以及很多不确定的困难,这对代码的移植非常不利。所以,为了便于代码从一个平台移植到另一个平台,可以将如上的函数接口进行封装。封装的该函数接口如下:
void VMovAptF(float* pfInput, float* pfOutput, int nDataLen)
{
#ifdef TI6678
int nDataLenTmp = 0;
nDataLenTmp = nDataLen*2;
if( (0 == (int)pfInput%8)&&( 0 == (int) pfOutput %8)&&( 0 == (int) nDataLen %8) )
{
DSP_blk_move((short*)pfInput, (short*)pfOutput, nDataLenTmp);
}
else
{
DSP_blk_move_cn((short*)pfInput, (short*)pfOutput, nDataLenTmp);
}
#endif
#ifdef VC
memcpy(pfOutput, pfInput, nDataLen*4);
#endif
}
从封装的函数接口VMovAptF可知,通过宏定义可以隔离不同系统之间的接口差异,从而将这些底层接口分别在DSP平台和VC平台生成不同的lib文件,供上层的Difar算法使用。
3 代码高效移植
3.1 算法流程图
Difar算法程序实现流程图如图2所示。首先将Difar算法用到的底层函数进行lib库文件形式封装;然后再供Difar算法中的解复用,互谱法等算法调用;最后将结果送出进行显示,实现Difar算法代码在不同平台之间的高效移植。
3.2 实现条件
在Intel x86硬件服务器平台进行验证,CPU为i7-4770、内存为32G、32核,操作系统为Windows,开发工具为Visual Studio 2010。
第一步:在VS中创建新项目,选择创建静态库模式;
第二步:将封装的函数置于AdaptFB.cpp中,同时创建包含函数声明的文件AdaptFB.h;
第三步:编译该项目,生成AdaptFb.lib文件;
第四步:在VS中新建空项目,然后在该项目中添加AdaptFB.h与lib库文件,在main函数文件中,添加#pragmacomment(lib, "AdaptFB.lib")。该语句表示引用AdaptFB.lib库,此时可以将Difar算法代码直接移植过来。
3.3 移植方式
将Difar代码直接复制到Win系统的VS2010的新建项目中,主要需要修改如下部分,然后进行微调,就可以实现代码移植:
(1)由于DSP板不同核间通过内存共享方式实现数据通信,而在Win系统的VS2010中,一个核的代码可以移植到一个项目中,多个核的代码则对应多个项目的代码,不同项目之间没有内存共享机制,故不同项目之间进行数据交互,需要修改为:通过调用[6]。
HANDLE
WINAPI
CreateThread(
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ SIZE_T dwStackSize,
_In_ LPTHREAD_START_ROUTINE lpStartAddress,
_In_opt_ __drv_aliasesMem LPVOID lpParameter,
_In_ DWORD dwCreationFlags,
_Out_opt_ LPDWORD lpThreadId
);
函数创建多个线程,采用UDP或者TCP方式进行网络通信,从而实现不同项目之间的数据交互。如果一次数据长度超过65,536 Byte,则需要将一次数据分成多次进行收发。
(2)由于DSP板中可以指定指针变量存储的地址空间以及大小,而Win系统的VS2010中不行,所以对于代码中的此类指针变量需要定义相应的数组,将指针变量引用到相应的数组即可。
(3)调用Sleep函数时,该函数的参数需要进行多次尝试,选择一个最佳的值。
3.4 实验验证
用模拟器投递一枚浮标,频率为300 Hz,方位为70°。将浮标的信号输入Difar算法中,处理结果如图3所示。
从图3中可以看出,在频率299.9 Hz处有一根亮线,表明Difar算法计算得到的频率为299.9 Hz,与实际的设置的频率300 Hz相差0.1 Hz。对于方位,预设值为70°,而Difar算法计算结果为69.8°,两者相差0.2°,这在允许范围之内。故移植后的代码Difar算法计算该情况正确。
接下来投递一枚浮标,频率为400Hz,方位为200°。将浮标的信号输入Difar算法中,处理结果如图4所示。
同理,从图4中可以看到,399.6 Hz处有根亮线,表明Difar算法计算的频率结果为399.6 Hz,与预设400 Hz,相差0.4 Hz。此种情况的频率相差比上述情况的要大,原因在于频率越高,在相同屏幕数据点数的情况下,频率分辨率越低,所以属于正常情况。而方位相差0.1°,在允许的范围之内,故移植代码计算该情况亦正确。
其他验证情况见表1所示。
表1 验证结果
从上图分析可以看出,Difar算法在Win系统VS2010平台下的计算结果与预设值是一致的,即预设值与实验值之间的误差在合理范围之内。将Difar算法从DSP到VS平台的移植,大部分工作也仅仅在于生成底层接口函数lib库,修改不同模块之间数据交互的方式,而不需要对Difar算法进行修改与验证,这使算法的移植节省了很大工作量。由此可见,基于lib库文件形式,通过宏定义隔离消除不同操作系统底层函数声明的差异形式实现Difar算法在不同系统上的高效移植是可行的。鉴于DSP板高昂的价格,以及PC电脑低廉的价格,此项工作具有十分重要的经济价值与现实意义。
4 结束语
本文对被动定向声纳浮标(Difar)算法原理进行了简单介绍,对不同系统之间底层接口函数进行lib库文件的封装思路与方法进行了详细的介绍;同时指出了Difar算法直接调用lib库封装后的底层函数,可以高效地从DSP板到Win操作系统的代码移植;最后进行了仿真实验验证。实验结果表明,基于lib库文件形式的Difar算法移植是高效的,同时,PC机与DSP板相比,价格上有显著优势,表明本文提出的高效的代码移植工作是非常有意义的,可在其他浮标算法移植过程中进行推广使用。但是该方法涉及到不同数据之间的交互需要通过多线程的方式进行,需要调用Sleep函数,而该函数参数不容易确定,取值小了会造成后续计算来不及,取值大了会多耗时,这方面需要进一步研究改进。