我需要盡快將大量資料寫入磁盤。從 MATLAB 我可以做到這一點fwrite:
function writeBinaryFileMatlab(data)
fid = fopen('file_matlab.bin', 'w');
fwrite(fid, data, class(data));
fclose(fid);
end
現在我必須做同樣的事情,但是來自 MATLAB 呼叫的 MEX 檔案。因此,我設定了一個 MEX 函式,該函式可以使用fstreamor寫入檔案fopen(受此
UPDATE 2
Wow I finally got something that's faster than MATLAB! 
uj5u.com熱心網友回復:
正如一些
uj5u.com熱心網友回復:
[不幸的是,這只是部分答案。]
這是一個 Windows 問題。我嘗試在 macOS 上重現您的結果,并發現了一種不同的有趣行為。我修改了您的代碼以區分 Cfwrite和 C std::fwrite,并添加了使用較低級別 Posix 撰寫的代碼write。
這是 C 代碼:
#include "mex.h"
#include <stdio.h>
#include <cstdio>
#include <fcntl.h>
#include <unistd.h>
void writeBinFile_c(int16_t *data, std::size_t size)
{
::FILE *fID = ::fopen("file_c.bin", "wb");
::fwrite(data, sizeof(int16_t), size, fID);
::fclose(fID);
}
void writeBinFile_std(int16_t *data, std::size_t size)
{
std::FILE *fID = std::fopen("file_std.bin", "wb");
std::fwrite(data, sizeof(int16_t), size, fID);
std::fclose(fID);
}
void writeBinFile_unix(int16_t *data, std::size_t size)
{
int fID = open("file_unix.bin", O_CREAT|O_WRONLY|O_TRUNC);
::write(fID, data, sizeof(int16_t) * size);
::close(fID);
}
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
const mxArray *mxPtr = prhs[0];
std::size_t nelems = mxGetNumberOfElements(mxPtr);
int16_t *ptr = (int16_t *)mxGetData(mxPtr);
double mode = -1;
if (nrhs > 1) {
mode = mxGetScalar(prhs[1]);
}
if (mode == 0) {
writeBinFile_c(ptr, nelems);
} else if (mode == 1) {
writeBinFile_std(ptr, nelems);
} else if (mode == 2) {
writeBinFile_unix(ptr, nelems);
} else {
mexErrMsgTxt("Wrong mode!");
}
}
這是MATLAB代碼:
mex -R2018a -Iinclude CXXFLAGS="$CXXFLAGS -O3" writefast.cpp
N = 10;
sizeMB = zeros(1,N);
t_matlab = zeros(1,N);
t_fwrite_c = zeros(1,N);
t_fwrite_std = zeros(1,N);
t_unix = zeros(1,N);
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: matlab\n')
t_matlab(k) = timeit(@() writeBinaryFileMatlab(data));
fprintf('TESTING: ::fwrite\n')
t_fwrite_c(k) = timeit(@() writefast(data, 0), 0);
fprintf('TESTING: std::fwrite\n')
t_fwrite_std(k) = timeit(@() writefast(data, 1), 0);
fprintf('TESTING: Unix write\n')
t_unix(k) = timeit(@() writefast(data, 1), 0);
end
% and plot result
figure
plot((sizeMB), t_matlab)
hold on
plot((sizeMB), t_fwrite_c)
plot((sizeMB), t_fwrite_std)
plot((sizeMB), t_unix)
legend('Matlab', 'C std lib', 'C Std lib', 'Unix')
xticks(sizeMB)
set(gca,'xscale','log','yscale','log')
function writeBinaryFileMatlab(data)
fid = fopen('file_matlab.bin', 'w');
fwrite(fid, data, class(data));
fclose(fid);
end
這些是兩次運行的輸出:

請注意時間是如何一致到 64 MB,然后發散。在 128 MB 及以上大小時,時間足以timeit在內部回圈中僅運行一次工具,因此您可以看到單個運行的中位時間,而不像在 64 MB 及以下大小時那樣對多次運行求平均值。所以對于 128 MB 及以上,我們看到時間在兩個不同的時間之間翻轉,這可能是快取的影響。但是在不同的運行中,不同的方法會變慢或變快,所以我很清楚它們都做同樣的事情。
因此,在 macOS 上,MATLABfwrite和 C 庫之間沒有區別fwrite。您看到的一定是 Windows 問題。
我很確定這與快取有關,因為:
這篇關于 Undocumented MATLAB 的文章討論了 的性能
fwrite,以及在默認情況下,MATLAB 如何在每次呼叫fwrite. 這在此處無關緊要,因為只有一次呼叫fwrite. 但帖子表明 MATLAB 函式處理快取的方式與 C 庫不同。C 庫的
fwrite作業方式就好像它要求fputc寫入每個位元組。它實際上可能不會這樣做,但這可能表明 Windows 上出了什么問題。請注意,在 Windows 上,MSVC 和 MinGW 編譯器使用相同的 C 庫msvcrt. 問題一定存在,并且 MATLAB 不能使用它來寫入檔案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/371522.html
