LabVIEW中管理大数据
LabVIEW的最大优势之一是自动内存管理。这种内存管理允许用户轻松创建字符串、数组和集群,而无需C/C++用户经常担心。但是,这种内存管理设计为绝对安全,因此数据被非常频繁地复制。这通常不会造成任何问题,但是当线路中的数据大小开始蔓延到兆字节范围时,副本开始引起内存问题,最终导致内存不足错误。虽然LabVIEW没有针对大型数据线进行优化,但它可以用于大型数据集,前提是程序员知道一些技巧,并为大型框图做好准备。
如何使用
1.大数据存储的方法
有时,需要在内存中存储大型数据集。要存储大型数据集而没有内存问题,需要一种存储机制,该机制允许保存数据的一个副本并以块的形式访问数据,从而允许在不占用大量内存的情况下传输数据。此问题的一个常见解决方案是函数全局,也称为移位寄存器全局。另一种解决方案是单元素队列。
可以使用VI服务器的重入VI创建C/C++指向缓冲区的指针的功能。该缓冲区产生对VI的引用,可以在任何地方传递。如果需要另一个缓冲区,请使用VI服务器启动另一个缓冲区。由于VI是可重入的,因此将创建另一个实例。现在可以传递此VI参考并在任何地方使用它。请注意,使用VI引用将导致对数据的任何访问都使用UI线程。使用UI线程进行数据访问会减慢程序执行速度。可以通过为每个缓冲区创建不同的VI并使每个VI不可重入来解决此问题。
GigaLabVIEW.llb中的GLV_WaveformBuffer.vi是功能全局概念的一个例子。要查看实际应用的概念,请打开GLV_TypicalMemoryStoreAndBrowse.vi。将点数设置为100或更多并运行VI。现在打开GLV_GigaLabVIEWMemoryStoreAndBrowse.vi并执行相同的操作。请注意响应能力和内存使用情况的差异。将点数增加到一百万或更多以查看主要差异。GLV_GigaLabVIEWMemoryStoreAndBrowse.vi使用GLV_WaveformBuffer.vi中的移位寄存器数据库来保存数据。该数据库还包含一个帧缓冲区-一个完整数据的预抽取数组,无需重新计算即可重用。它还使用上一示例中已经引入的分块和显示算法。
GigaLabVIEW.llb中的GLV_GigaLabVIEWMemoryStoreAndBrowseQ.vi是单元素队列概念的一个例子。它使用标准的面向对象技术来创建队列并对其进行操作。用途与GLV_GigaLabVIEWMemoryStoreAndBrowse.vi相同。在本例中,GLV_WaveformBuffer.vi中的不同移位寄存器作为单独的队列实现。使用哪种方法在很大程度上取决于品味和编程风格。
现在已经知道如何创建大型数据集,可以期望分配多少内存?答案取决于几个因素。当LabVIEW分配一个数组时,它会请求一个连续的内存部分。如果内存碎片化,即使仍有数百兆字节的可用内存,也可能会出现内存不足错误。可以通过将数据分块分配来解决此问题。如果正确编写了存储库VI,则对它的访问不应更改。LabVIEW使用签名的32位内存访问,因此总内存绝不会超过2GB。Windows操作系统使用无符号的32位内存访问,但保留高2GB的内存供系统使用,并仅允许在低2GB的内存中执行程序(服务器版本更灵活)。此外,系统DLL占据了2GB用户数据空间中大部分的高四分之一。因此,Windows系统的实际限制是1.0-1.5GB。
不同版本的LabVIEW以不同方式对内存进行分段。这将更改可以分配的最大数组大小。在LabVIEW7中。x及更高版本,通常可以在单个阵列中分配略高于1GB的带宽。LabVIEW8.x由于其较大的功能集,仅允许最大数组大小约为800MBytes。
2.显示数据
要查看实际速度改进,请从GigaLabVIEW.llb打开GLV_TypicalGenerateAndDisplay.vi。打开操作系统的内存监视器。将点数设置为1万或更多并运行它。请注意执行时间和内存使用。关闭VI。现在打开并使用相同的点数运行GLV_GigaLabVIEWGenerateAndDisplay.vi。请注意时间和内存使用情况的差异。GLV_TypicalGenerateAndDisplay.vi使用标准LabVIEW正弦波发生器一次生成整个数据集,然后绘制到屏幕上。GLV_GigaLabVIEWGenerateAndDisplay.vi以块的形式生成数据,抽取这些块,然后丢弃原始数据。它还使用较低级别的正弦波发生器来生成一个简单的数组。当波形数据类型用于图形时,点数足够低,因此复制的成本不是很高。请注意,将该VI从波形数据类型正弦发生器转换为使用较低级别的简单阵列发生器,可在LabVIEW20.7及更高版本中将速度提高20%。
3.突破2GB文件大小障碍(LabVIEW7.1及更早版本)
LabVIEW8.0引入了64位文件指针,因此不需要本节中的技术。早期版本的LabVIEW使用32位有符号整数作为文件指针。这直接将文件的可寻址大小限制为2GB。以10MBytes/s的速度串流到磁盘,这是使用NI数字化仪轻松完成的,在32分3秒内填满20位有符号整数空间。有两种直接选择可以解决此问题。
第一个相当简单。如果使用的是具有NTFS格式磁盘分区(必须是Windows NT,2000或XP)的Windows操作系统,则只需使用LabVIEW写入基元即可写入磁盘。不要将任何东西连接到偏移,并将位置模式连接到电流。可以写入,直到磁盘空间用完为止。
对于一个简单的例子,在GigaLabVIEW.llb中打开GLV_StreamToDisk.vi。本示例将双精度浮点数的升序保存到磁盘。在前面板上设置数据量,运行,然后在存储数据时坐下来放松。默认块大小65,000字节经实验确定为基于Windows的系统的最佳速度。
要读回数据,请反向执行该过程。使用没有偏移输入的读取基元。最多可以使用2GB边界的偏移量。如果在该边界之外使用它,则会收到文件结束错误。但是,如果只是按顺序从磁盘读取数据,则可以读取直到文件末尾。VIGLV_ReadFromDisk.vi显示了这个过程。
此技巧仅适用于上述Windows操作系统。此外,无法在文件中查找高于2GB边界的任意位置并读取那里的数据。
这将我们带到了第二个选项–将64位文件工具与LabVIEW配合使用。一个很好的例子是HDF5。HDF5是由美国国家超级计算应用中心(NCSA)设计、编写和维护的二进制分层文件实用程序。它是免费的,因为它是由美国政府资助的。有关HDF5的完整信息、源代码和二进制文件,请访问http://hdf.ncsa.uiuc.edu/HDF5/。使用HDF5或任何其他64位实用程序需要能够将64位数字传递给实用程序。这就引出了最后一个话题。
4.与64位DLL接口(LabVIEW7.1及更早版本)
LabVIEW8.0引入了对64位整数的完全支持,因此不需要本节中的技术。对于早期版本,有两个选项可用于与64位DLL接口。第一种是编写一个C/C++包装器,它只公开LabVIEW可以本地处理的数据结构。由于这有没有了LabVIEW的易用,我们将讨论第二种选择-使用调用库节点并直接访问DLL,使用一些数字技巧。
可以通过两个64位数字的群集来表示32位数字。64位数字之间的数学运算可以使用众所周知的算法进行编码,以实现任意精度的算术。这些算法超出了本文的范围,但可以在Web上轻松找到它们。
现在有了一种表示64位数字并对其进行数学运算的方法,如何将它们获取到DLL?最简单的方法是将64位实体类型转换为双精度值,然后在DLL请求64位整数时传入双精度值。由于类型转换执行二进制图像转换,类似于C中的并集,因此只要有正确顺序的高阶和低阶双字,一切都会很好。下图显示了正确的顺序和转换为double格式。
调用库节点将负责特定平台的字节排序。此方法也适用于数组,甚至可以在需要它的体系结构(如SPARC)上提供正确的填充。这是因为双精度是一个64位实体。因此,如果DLL具有以下函数原型: int32 fooFunc(uint64 length, uint64 *elements)
在调用库节点中创建的原型如下所示
Long fooFunc(double length, double *elements).
不能使用此技巧获取函数的返回值。如果希望使用的功能具有原型
uint64 barFunc(void)
那么旧版本的LabVIEW就无法访问完整的返回值。LabVIEW只能获取底部的32位因为函数返回值在处理器的寄存器中返回,而调用列表中的项目则在程序堆栈中返回。在堆栈上,唯一重要的是LabVIEW和DLL使用相同大小的对象。对于函数返回值,整数和浮点值在不同的寄存器中返回。LabVIEW无法访问返回的32位整数的前64位。C/C++包装器是必需的。使用上面的例子,包装器的形式是
void barFuncWrapper(uint64 *barFuncData){
*barFuncData = barFunc();
return;
}
幸运的是,这通常不是必需的。NI产品提供了两个与64位DLL接口的示例–两个接口都与HDF5连接。
HWS文件工具是一个C/C++包装器,设计时考虑了LabVIEW接口。由于HDF5的级别非常低且难以掌握,HWSAPI在HDF5复杂性上放置了标准的LabVIEW文件I/O接口。HWS目前可与NI-HSDIO、NI-SCOPE和NI-FGEN驱动程序、模拟和数字波形编辑器以及2004年<>月及以后的任何驱动程序CD一起提供。
sfpFile实用程序集是一个LabVIEW实用工具,可直接连接HDF5,使用尽可能少的C封装器。它可从ni.com获得,但不受NI的支持。它体现了直接使用LabVIEW的64位DLL的原则。此实用程序集中的两个示例VI包含在GigaLabVIEW.llb中。第一个是H5Screate_simple.vi,它是对带有原型的HDF5DLL的直接调用。
int32 H5Screate_simple(int32 rank, const uint64 *dims, const uint64 *maxdims).
LabVIEW调用库节点原型是
long H5Screate_simple(long rank, double *dims, double *maxdims).
第二个是DU64_DBLToDU64.vi,这是一个如何将双精度浮点数转换为两个32位整数的簇的示例,然后转换回双精度以传递给HDF5例程。双精度提供了一种方便的方法来跟踪LabVIEW中的大文件指针整数,因为其精度为52位。由于NTFS只有48位数据空间,因此效果很好。整数值浮点数的加法、减法和乘法通常是精确运算。
请注意,HWS和sfpFile生成相同的文件格式。只是API不同。
5.示例代码
GigaLabVIEW.llb包含本教程中提到的所有示例代码。如果愿意,还可以下载HDF5DLL以防止HDF5示例查找不存在的库。将它们放在系统目录中。
这是LabVIEW的一个功能介绍,更多的使用方法与开发案例,欢迎登录官网,了解更多信息。有需要LabVIEW项目合作开发,请与我们联系。
厂家没有提供LabVIEW的例子。根据通讯协议的相关的说明,编写了适合项目的程序。程序截图如下所示。
相关资料说明,如下所示。
LabVIEW程序,如下附件所示。