我想從一個大的(約 11 GB)二進制檔案中讀取部分內容。當前可行的解決方案是使用 加載整個檔案 ( raw_data) fread(),然后裁剪出感興趣的部分 ( data)。
問題:是否有更快的方法來讀取檔案的小部分(占總檔案的 1-2%,部分順序讀取),給定 Matlab 中的二進制掩碼(即特定位元組的邏輯索引)?具體如下。
我的具體案例的注意事項:
data感興趣的(26 e6 位元組,或約 24 MB)大約是raw_data(1.2e 10 位元組或約 11 GB)的 2%- 每 600.000 位元組包含 ca 6.500 位元組讀取,可以分解為大約 1.200 個讀取跳過周期(例如“讀取 10 個位元組,跳過 5000 個位元組”)。
- 整個檔案的讀取指令可以分解為大約 20.000 個類似但(不完全相同)的讀取跳過周期(即大約 20.000x1.200 個讀取跳過周期)
- 從 GPFS(并行檔案系統)讀取檔案
- 過多的 RAM、最新的 Matlab 版本和所有工具箱都可用于該任務
我最初關于 fread-fseek 回圈的想法被證明比讀取整個檔案要慢得多(見下面的偽代碼)。分析顯示fread()是最慢的(被呼叫超過一百萬次可能對這里的專家來說是顯而易見的)。
我考慮的替代方案:memmapfile()[

uj5u.com熱心網友回復:
我會做兩件事來加快你的代碼:
- 預分配資料陣列。
- 撰寫一個 C MEX 檔案來呼叫
fread和fseek.
這是我使用MATLAB 或 Cfread進行比較的快速測驗:fseek
%% Create large binary file
data = 1:10000000; % 80 MB
fi = fopen('data.bin', 'wb');
fwrite(fi, data, 'double');
fclose(fi);
n_read = 1;
n_skip = 99;
%% Read using MATLAB
tic
fi = fopen('data.bin', 'rb');
fseek(fi, 0, 'eof');
sz = ftell(fi);
sz = floor(sz / (n_read n_skip));
data = zeros(1, sz);
fseek(fi, 0, 'bof');
for ind = 1:sz
data(ind) = fread(fi, n_read, 'int8');
fseek(fi, n_skip, 'cof');
end
toc
%% Read using C MEX-file
mex fread_test_mex.c
tic
data = fread_test_mex('data.bin', n_read, n_skip);
toc
這是fread_test_mex.c:
#include <stdio.h>
#include <mex.h>
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
// No testing of inputs...
// inputs = 'data.bin', 1, 99
char* fname = mxArrayToString(prhs[0]);
int n_read = mxGetScalar(prhs[1]);
int n_skip = mxGetScalar(prhs[2]);
FILE* fi = fopen(fname, "rb");
fseek(fi, 0L, SEEK_END);
int sz = ftell(fi);
sz /= n_read n_skip;
plhs[0] = mxCreateNumericMatrix(1, sz, mxDOUBLE_CLASS, mxREAL);
double* data = mxGetPr(plhs[0]);
fseek(fi, 0L, SEEK_SET);
char buffer[1];
for(int ind = 1; ind < sz; ind) {
fread(buffer, 1, n_read, fi);
data[ind] = buffer[0];
fseek(fi, n_skip, SEEK_CUR);
}
fclose(fi);
}
我看到這個:
Elapsed time is 6.785304 seconds.
Building with 'Xcode with Clang'.
MEX completed successfully.
Elapsed time is 1.376540 seconds.
That is, reading the data is 5x as fast with a C MEX-file. And that time includes loading the MEX-file into memory. A second run is a bit faster (1.14 s) because the MEX-file is already loaded.
In the MATLAB code, if I initialize data = []; and then extend the matrix every time I read like OP does:
tmp = fread(fi, n_read, 'int8');
data = [data, tmp];
then the execution time for that loop was 159 s, with 92.0% of the time spent in the data = [data, tmp] line. Preallocating really is important!
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/435040.html
