【问题标题】:How to export data from C to MATLAB (on different machines)如何将数据从 C 导出到 MATLAB(在不同的机器上)
【发布时间】:2012-10-31 22:42:56
【问题描述】:

我正在 Linux 集群上的 C 程序中生成长双浮点数据。我需要将数据导出到集群上没有安装的Matlab。

最好的方法是什么?我的顾问说使用printf 语句导出。我假设他的意思是将数据发送到逗号分隔的文件(和fprintf)。但在我看来,这可能会很慢并且使用太多内存,我们可能会失去很多精度。

我找到了用于读写 .MAT 文件的 this web page,但我不太了解该页面,或者我复制到集群但无法编译的 the example(因为它缺少库,显然,来自 MATLAB。

将数据从 Linux/C 导出到 Windows/MATLAB 的最佳、最简单或最快的方法是什么?我如何开始使用该方法? 当您回答我对 C 语言很陌生并且可能需要帮助以了解如何获取、安装、配置和链接任何库时,请注意。但是一旦完成,我认为我很擅长学习使用它们。

【问题讨论】:

    标签: c linux matlab


    【解决方案1】:

    为什么你认为你会失去精确度? CSV 的唯一缺点是 ASCII 文件比二进制文件需要更多的存储空间,但在当今时代,你可以以理发的价格获得 TB 的存储空间,这似乎不是问题。

    如果您在千兆字节上写入千兆字节,它只会明显变慢,但通常计算需要更长的时间,以至于 ASCII 和二进制之间的差异完全可以忽略不计(如果计算花这么长时间:那你为什么需要一个集群?)

    无论如何,我会选择 ASCII——如何写入和读取一些二进制 blob 需要在两个地方记录,在写入端和读取端都更容易产生错误,更难解决它们是因为没有人可以读取文件等。此外,MAT 文件格式可能会在下一个 Matlab 版本中发生变化(就像过去一样)。

    使用 ASCII,你没有这些问题,我能想到的唯一缺点是你必须在 Matlab 中编写一个小型集群特定文件阅读器(这仍然比解决所有错误和维护一个 MAT 文件编写器)。

    无论如何,Matlab 中有大量工具可用于 ASCII:textreaddlmreadimportdata 等等。在 C 端,确实只使用fprintf(文档here)。

    【讨论】:

    • +1:我同意鲁迪的观点。对于新手来说这将是最简单的解决方案,并且新手会更快地找到解决方案(我不猜测它是否会提供更快的解决方案)。这是否是最好的方法取决于一个人的观点。
    • @High Performance Mark, atRody(他们不会让我放两个“@”):感觉我可能会失去精度,因为我似乎找不到格式字符串 width.precision 用于打印的值“所有可用的精度”。如果我没有在格式字符串中指定数字(例如,“%g%f%e),它似乎有一个默认截止值。但显然你以同样的方式打印二进制文件。我会弄清楚什么这些数字是。感觉它会更慢,因为我已经多次要求某个程序或其他程序读取一个大文本文件,并且该程序永远不会返回(也就是说,它挂起)。我承认,这不是很科学。
    • 文本导入足够快。 Matlab 的精度不如 C 输出,因此保存精度不是问题。
    【解决方案2】:

    我曾经也遇到过这个问题(嗯,有点……),并使用了一种简单的二进制格式来完成这项工作。

    如果您的数据格式是静态的,这意味着如果它永远不会改变,您可以将自己限制在您真正需要的范围内,并在加载程序中硬编码确切的格式。但是,如果您想灵活地添加和删除列,则应该定义一种标题来添加有关数据格式的信息并在读取时对其进行评估。

    简单导入数据的技巧如下:

    • 让 MATLAB 程序知道您的数据记录有多长以及它们是如何组成的。
    • 读取数据

      rest = fread(fid, 'uchar=>uint8', 'b').';
      

      为了得到uint8s的行向量。

    • 重塑数据
      rest = reshape(rest, recordlength, []).';
      

      为了在recordlength 列中获取您的数据,并根据需要获取尽可能多的行。

    • 对于每个数据列,将相关的uint8 行组合成一个“子矩阵”,使用reshapetypecastswapbytes 的组合对数据进行适当分组并将它们转换为所需的格式.

      这里最重要的是typecast() function,它接受“按字节”数据作为第一个参数,所需的数据类型作为第二个参数。有多种可接受的数据类型,例如intXXuintXXXX81632 和 (AFAIK) 64 之一)以及@987654338 @和double

      例如,typecast([1, 1], 'uint16') 给你257,而typecast([0, 0, 96, 64], 'float') 给你3.5

    这样做后,与文本文件相比,您可以将阅读速度提高 20 倍左右。 (至少,在我编写的应用程序中就是这种情况:每 10 毫秒大约有 10 个不同的测量值,一次测量可能是几分钟甚至几小时,我想尽可能快地读入这样的文件。所以我将这些东西从文本重新编码为二进制,并获得了大约 20 倍,或者可能是 15 倍 - 不知道确切。但它很多......)

    【讨论】:

    • 您能否澄清“如果您的数据格式是静态的”以及整个段落。我对C相当陌生,只是感觉自己的方式。我(不应该)遗漏了一些细节:数据是随时间生成的,我想为每个循环写出来。数据位于声明为realtype z[2*N] = {0}; 的结构中,realtypelong double。谢谢。
    • @Jeff 这意味着:如果您事先知道您将拥有哪些数据并且很少或永远不会更改,您可以在您的 MATLAB 应用程序中对读数进行硬编码。但是,如果您想保持灵活性并在以后添加/删除/更改列和/或其类型,则必须将替代项编码到文件中。据我所知,你每次只有一个价值,没有别的,这会“永远”保持这种状态吗?这样您就不必担心读取器端确定数据格式。
    • @Jeff 一个问题可能是您有一个long double,据我所知,它在 MATLAB 中没有等效项。 (我在这里吗?)所以你必须在写作时重新编码到double
    【解决方案3】:

    如您所说,我会将工作区保存为 .MAT 文件。然后,您可以将所有当前变量中包含的任何值保存为当时的工作区。但是,如果您正在读取千兆字节长的数组(您的数据),那么您可能会逐块读取它们(可能是由于 RAM 限制?)并且在这种情况下保存工作空间可能对您没有帮助。

    我永远不会打印任何东西来运输。在我的工作中(长时间渐近,所以我有大量的输出),我使用 fwrite 将所有内容保存为二进制文件。据我所知,转换为文本既慢又昂贵。

    我希望这会有所帮助!

    【讨论】:

    • 可能我不清楚。数据以 C 语言(在 Linux 上)开始,需要移动到 MATLAB(在 Windows 上)。所以我认为你的建议是相反的。
    • 好的,比如你的数据有多大?
    • 它将非常大。我们将进行多次运行。但是一次运行可能是长时间跨过 16 个数据点,每秒导出一次数据点。换句话说,多行乘以 16 列的长浮点数。那有意义吗?和帮助?
    • 那我会尝试这样做。在每次迭代(第二次)时,将数据转储为二进制文件(我相信这是最快和最便宜的 - 'fwrite')。每 T 次迭代后,关闭文件。应该在此处调用另一个脚本并将此文件发送到 matlab 所在的其他集群。同时,您的迭代应该继续将数据转储到新的 bin 文件中。在 Matlab 方面,很容易逐个文件读取它们,每个文件都包含 T 秒/迭代的数据。您可以使用任何并行编程工具来运行这两个模块。选择一个最佳的 T 大小。这有帮助吗?
    • 好的。我必须去阅读有关fwrite 的信息。我正在考虑转储数据并按时间分离。也就是说,不是每 T 次迭代,而是每 T 小时创建一个新文件。通过迭代来做会更好吗?
    猜你喜欢
    • 2013-08-28
    • 2017-01-29
    • 2017-05-03
    • 1970-01-01
    • 2015-12-01
    • 2019-04-26
    • 1970-01-01
    • 2011-01-18
    • 2019-03-07
    相关资源
    最近更新 更多