簡體   English   中英

加快c中文本文件讀取速度的可能替代方法?

[英]Possible alternatives to speed up reads from a text file in c?

我正在使用機器學習應用程序,其中我的功能存儲在巨大的文本文件中。 目前,我已經實現了數據輸入讀取的方式,這是緩慢實用的方式。 基本上,文本文件的每一行代表稀疏格式的特征向量。 例如,以下示例包含index:value形式的三個功能。

1:0.34 2:0.67 6:0.99 12:2.1 28:2.1
2:0.12 22:0.27 26:9.8 69:1.8
3:0.24 4:67.0 7:1.9 13:8.1 18:1.7 32:3.4

以下是我現在進行閱讀的方式。 因為我之前不知道特征字符串的長度,所以我只是讀了一個適當大的長度,該長度上限是每個字符串的長度的上限。 一次,我從文件中讀取了這一行,我只是使用strtok_r函數將字符串拆分為鍵值對,然后進一步對其進行處理以存儲為稀疏數組。 任何關於如何加快速度的想法都受到高度贊賞。

FILE *fp = fopen(feature_file, "r");

int fvec_length = 0;
char line[1000000];
size_t ln;
char *pair, *single, *brkt, *brkb;

SVECTOR **fvecs = (SVECTOR **)malloc(n_fvecs*sizeof(SVECTOR *));
if(!fvecs) die("Memory Error.");

int j = 0;

while( fgets(line,1000000,fp) ) {
    ln = strlen(line) - 1;
    if (line[ln] == '\n')
        line[ln] = '\0';

    fvec_length = 0;
    for(pair = strtok_r(line, " ", &brkt); pair; pair = strtok_r(NULL, " ", &brkt)){
        fvec_length++;
        words = (WORD *) realloc(words, fvec_length*sizeof(WORD));
        if(!words) die("Memory error.");
        j = 0;
        for (single = strtok_r(pair, ":", &brkb); single; single = strtok_r(NULL, ":", &brkb)){
            if(j == 0){
                words[fvec_length-1].wnum = atoi(single);
            }
            else{
                words[fvec_length-1].weight = atof(single); 
            }
            j++;
        }
    }   
    fvec_length++; 
    words = (WORD *) realloc(words, fvec_length*sizeof(WORD));
    if(!words) die("Memory error.");
    words[fvec_length-1].wnum = 0;
    words[fvec_length-1].weight = 0.0;

    fvecs[i] = create_svector(words,"",1);
    free(words);
    words = NULL;
}
fclose(fp);
return fvecs;
  1. 您應該絕對減少內存分配的數量。 經典方法是將每個分配的向量加倍,以便獲得分配調用的對數而不是線性。

  2. 由於您的行模式似乎恆定,因此無需手動對其進行標記,請在每條加載的行上使用單個sscanf()直接掃描該行的單詞。

  3. 您的行緩沖區似乎非常大,這可能會消耗大量堆棧,從而使緩存局部性惡化。

可能在調用realloc時,您正在執行系統調用。 系統調用是一項昂貴的操作,涉及上下文交換以及從用戶到內核空間的切換,反之亦然。

似乎您正在為獲得的每對令牌執行一次realloc調用。 這是很多電話。 您不必在意之前將1MByte分配給文件所指向的緩沖區。 為什么對單詞指向的緩沖區這么保守?

我發現在Linux(Fedora)上,realloc()非常高效,並且不會減慢速度。 在Windows上,由於內存的結構方式,可能會造成災難性的后果。

我對“長度未知的行”問題的解決方案是編寫一個函數,該函數對fgets()進行多次調用,將結果串聯起來,直到檢測到換行符為止。 該函數接受&maxlinelength作為參數,如果對fgets()的任何調用都會導致串聯的字符串超過maxlinelength,則將調整maxlinelength。 這樣,只有在找到最長的行之前,才重新分配新的內存。 同樣,如果已調整maxlinelength,則只需要為WORD重新分配()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM