gpt4 book ai didi

c++ - 在 MEX 中超快地将二进制文件写入磁盘

转载 作者:行者123 更新时间:2023-12-05 02:36:55 26 4
gpt4 key购买 nike

我需要尽快将大量数据写入磁盘。在 MATLAB 中,我可以使用 fwrite 来做到这一点:

function writeBinaryFileMatlab(data)
fid = fopen('file_matlab.bin', 'w');
fwrite(fid, data, class(data));
fclose(fid);
end

现在我必须做同样的事情,但是从 MATLAB 调用的 MEX 文件。因此,我设置了一个可以使用 fstreamfopen 写入文件的 MEX 函数(受 this SO post 的结果启发)。然而,这比从 MATLAB 调用 fwrite 慢得多,如下所示。为什么会这样,我可以做些什么来提高 MEX 函数的写入速度。

#include "mex.h"
#include <iostream>
#include <stdio.h>
#include <fstream>

using namespace std;

void writeBinFile(int16_t *data, size_t size)
{
FILE *fID;
fID = fopen("file_fopen.bin", "wb");
fwrite(data, sizeof(int16_t), size, fID);
fclose(fID);
}

void writeBinFileFast(int16_t *data, size_t size)
{
ofstream file("file_ostream.bin", std::ios::out | std::ios::binary);
file.write((char *)&data[0], size * sizeof(int16_t));
file.close();
}

void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
const mxArray *mxPtr = prhs[0];
size_t nelems = mxGetNumberOfElements(mxPtr);
int16_t *ptr = (int16_t *)mxGetData(mxPtr);
#ifdef USE_OFSTREAM
writeBinFileFast(ptr, nelems);
#else
writeBinFile(ptr, nelems);
#endif
}

然后我使用以下脚本检查性能:

mex -R2018a -Iinclude CXXFLAGS="$CXXFLAGS -O3" -DUSE_OFSTREAM main.cpp -output writefast_ofstream
mex -R2018a -Iinclude CXXFLAGS="$CXXFLAGS -O3" main.cpp -output writefast_fwrite

for k = 1:10
sizeBytes = 2^k * 1024 * 1024;
fprintf('Generating data of size %i MB\n', sizeBytes / 2^20)
M = sizeBytes / 2; % 2 bytes for an int16
sizeMB(k) = sizeBytes / 2^20;
data = int16(rand(M, 1) * 100);

fprintf('TESTING: write matlab\n')
t_matlab(k) = timeit(@() writeBinaryFileMatlab(data));

fprintf('TESTING: write ofstream\n')
t_ofstream(k) = timeit(@() writefast_ofstream(data), 0);

fprintf('TESTING: write fwrite\n')
t_fwrite(k) = timeit(@() writefast_fwrite(data), 0);
end

% and plot result
figure(14); clf;
plot((sizeMB), t_matlab)
hold on
plot((sizeMB), t_ofstream)
plot((sizeMB), t_fwrite)
legend('Matlab', 'ofstream', 'fwrite')
xticks(sizeMB)

这给了我下面的情节。为什么从 MATLAB 调用 fwrite 比从 MEX 调用快得多?我如何才能在我的 MEX 函数中达到相同的速度?

我使用的是 Windows 10。配备 Core i7、SSD 的笔记本电脑。


更新

我尝试了评论中的各种建议,但仍然没有达到 MATLAB 的 fwrite 性能。请在此处查看带有源代码的存储库:https://github.com/rick3rt/saveBinaryDataMex

这是 MSVC 2017 的结果,结合了 rahnema1 的建议:

enter image description here

更新 2

哇,我终于得到了比 MATLAB 更快的东西! Rahnema1's答案成功了:)这里结合了所有建议方法的数字(完整的 src 可以在 Github 上找到)。

enter image description here

最佳答案

如某些 posts 中所示非常大的缓冲区往往会降低性能。所以缓冲区是一部分一部分写入文件的。对我来说,8 MiB 提供了最佳性能。

void writeBinFilePartByPart(int16_t *int_data, size_t size)
{
size_t part = 8 * 1024 * 1024;

size = size * sizeof(int16_t);

char *data = reinterpret_cast<char *> (int_data);

HANDLE file = CreateFileA (
"windows_test.bin",
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);

// Expand file size
SetFilePointer (file, size, NULL, FILE_BEGIN);
SetEndOfFile (file);
SetFilePointer (file, 0, NULL, FILE_BEGIN);

DWORD written;
if (size < part)
{
WriteFile (file, data, size, &written, NULL);
CloseHandle (file);
return;
}

size_t rem = size % part;
for (size_t i = 0; i < size-rem; i += part)
{
WriteFile (file, data+i, part, &written, NULL);
}

if (rem)
WriteFile (file, data+size-rem, rem, &written, NULL);

CloseHandle (file);
}

将输出与@Cris Luengo 提到的 C++ Std lib 方法进行比较:

enter image description here

关于c++ - 在 MEX 中超快地将二进制文件写入磁盘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70126690/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com