通過@軸突的回答啓發,我實現了一個「快」 C程序將文件轉換爲二進制文件,然後使用Matlab的fread
功能閱讀。擾流警報:讀數然後快20倍......雖然初始轉換需要一點時間。
爲了使Matlab中的工作更容易,文件大小更小,我將每個數字字段轉換爲一個int16
(短整數)。對於第一個領域 - 看起來像一個yyyymmdd領域 - 涉及分裂成兩個較小的數字;同樣的十進制數字轉換爲兩個短整數(給定我認爲有效的表觀範圍)。所有這些都意識到「要真正優化,你必須真正瞭解你的問題」 - 所以如果假設無效,結果也會如此。
這裏是C代碼:
#include <stdio.h>
int main(){
FILE *fp, *fo;
long int ld1;
int d2, d3, d4, d5, d6, d7;
short int buf[9];
char c8;
int n;
short int year, monthday;
fp = fopen("bigdata.txt", "r");
fo = fopen("bigdata.bin", "wb");
if (fp == NULL || fo == NULL) {
printf("unable to open file\n");
return 1;
}
while(!feof(fp)) {
n = fscanf(fp, "%ld %d:%d.%d %d.%d %d %c\n", \
&ld1, &d2, &d3, &d4, &d5, &d6, &d7, &c8);
year = d1/10000;
monthday = d1 - 10000 * year;
// move everything into buffer for single call to fwrite:
buf[0] = year;
buf[1] = monthday;
buf[2] = d2;
buf[3] = d3;
buf[4] = d4;
buf[5] = d5;
buf[6] = d6;
buf[7] = d7;
buf[8] = c8;
fwrite(buf, sizeof(short int), 9, fo);
}
fclose(fp);
fclose(fo);
return 0;
}
得到的文件是原來的一半大小 - 這是令人鼓舞的,將加快進入。請注意,如果輸出文件可以寫入與輸入文件不同的磁盤,這將是一個不錯的主意 - 它確實有助於在查找操作中浪費大量時間而不浪費大量時間。基準:使用一個2 M行的文件作爲輸入,它在大約2秒鐘內運行(相同的磁盤)。產生的二進制文件與下面的閱讀在Matlab:
tic
fid = fopen('bigdata.bin');
d = fread(fid, 'int16');
d = reshape(d, 9, []);
toc
當然,現在如果你要恢復的數字爲浮點數,你必須做的工作一點點;但我認爲這是值得的。您需要解決的一個可能的問題是小數點後的值具有不同數字位數的情況:當b> 100時,將(a,b)轉換爲浮點數不像「a + b/100」那麼簡單...「學生練習」?
有點基準:上面的代碼花了大約0.4秒。相比之下,我對textread
的第一個建議在同一個文件上花了大約9秒;並且您的原始代碼需要超過11秒。當文件變大時,差異可能會變大。
如果你這麼做(如你所說),顯然值得將文件轉換爲二進制格式,並以這種方式使用它們。特別是如果文件只需轉換一次,並多次讀取,則節省的成本相當可觀。
更新
我反覆基準用13M線文件。轉換花費了13秒,二進制讀取了3秒<。相比之下,其他兩種方法都花了一分鐘(textscan:61s; fscanf:77s)。看起來事情是線性縮放的(文件大小470M文本,240M二進制文件)
「太慢了」/「快速運行」 - >你能用一個單位時間表示嗎? –
另外,重塑命令需要多長時間?我想大多數時間都在閱讀文件,但你可以檢查嗎? – Engineero
你有足夠的內存來保存整個陣列嗎?大約35字節的行中的1.6 GB(目測)意味着大約5000萬行 - 次8個字節的7個數= 2.8 GB。在您重新塑造時,可能需要兩個陣列副本。大到足以檢查這不是問題... – Floris