[英]C++ Linux fastest way to measure time (faster than std::chrono) ? Benchmark included
[英]Fastest way to count lines in file in MATLAB (Perl faster than C?)
在研究中,我必須計算10+ GB的csv文件中的行數。 在MATLAB上執行此操作的經典方法似乎是使用\\n
作為分隔符的textscan()
,但這會占用大量內存,而且速度非常慢。 建議我編寫一個Perl腳本,並使用str2double(perl('countlines.pl', path))
調用它,這似乎要快得多:
# countlines.pl
while (<>) {};
print $.,"\n";
然后,我想看看我是否可以編寫一個在C中執行相同功能但沒有運氣的MEX函數,是否具有任何優勢,更令人驚訝的是,我發現它比Perl腳本慢了大約10倍(使用LLVM編譯器Xcode 4.6.3):
//countlines.c
#include "mex.h"
void countlines(char *filepath, double *numLines)
{
/* Routine */
numLines[0] = 0;
FILE *inputFile = fopen(filepath, "r");
int ch;
while (EOF != (ch=getc(inputFile)))
if ('\n' == ch)
++numLines[0];
}
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
/* Gateway function */
int bufferLength, status;
char *filepath; // Input: File path
double *numLines; // Output Number of lines
bufferLength = (mxGetM(prhs[0]) * mxGetN(prhs[0])) + 1; // Get length of string
filepath = mxCalloc(bufferLength, sizeof(char)); // Allocate memory for input
// Copy the string data from prhs[0] into a C string
status = mxGetString(prhs[0], filepath, bufferLength);
if (status != 0)
mexErrMsgIdAndTxt("utils:countlines:insufficientSpace", "Insufficient space, string is truncated.");
// Create the output matrix and get a pointer to the real data in the output matrix
plhs[0] = mxCreateDoubleMatrix(1,(mwSize)1,mxREAL);
numLines = mxGetPr(plhs[0]);
// Call the C routine
countlines(filepath, numLines);
}
所以,
除了網關功能之外,MEX功能中的這些開銷又來自何處?
無法與Perl的簡單行計數功能進行比較,因為它們在功能上並不等效。
我還能做些什么來加快速度? 是的,只數行。
沒有多余的東西,例如以雙精度矩陣讀取。
這是使用C ++對文本文件中的行進行計數的示例:
std::ifstream text_file(/*...*/);
std::string text_from_file;
unsigned int line_count = 0;
while (std::getline(text_file, '\n'))
{
++line_count;
}
比較性能時,功能必須等效。
編輯1:
決定。 你在數線嗎?
您是否要計算矩陣中的行數?
你想只算在一個文件中的行?
如果要計算矩陣中的行數,則需要修改Perl腳本。
如果希望MEX函數僅對行進行計數,請刪除對計數線功能的調用countlines
所有內容。
為什么要使用double
行數?
您是否期望小數行計數?
您要使用CI / O還是C ++ I / O?
逐塊讀取數據將加快CI / O功能:
#define MAX_CHUNK_SIZE 1024*1024
char buffer[MAX_CHUNK_SIZE];
size_t chars_read = 0;
unsigned int line_count = 0;
//...
while (!feof(inputFile))
{
chars_read = fread(buffer, 1, MAX_CHUNK_SIZE, input_file);
char c;
for (unsigned int i = 0; i < chars_read; ++i)
{
if (c == '\n')
{
++line_count;
}
}
}
訪問文件的瓶頸是查找數據的開銷。 大量讀取可減少開銷。
您是否已閱讀有關此主題的Perl常見問題解答,其中提供了大約6個示例?
wc
命令已被移植到Windows,因此如果要安裝它可能是最好的解決方案。 否則,我將在wc
示例之前使用Perl示例(下面已修復和優化)。
my $lines = 0;
open my $fh, '<:raw', $filename
or die "Can't open $filename: $!";
while( sysread $fh, $buffer, 64*1024 ) {
$lines += ( $buffer =~ tr|\n||; );
}
close $fh;
在這段代碼中要計算總行數。 但是,這需要幾個迷你。
my $lines = do {
open my $fh, '<', "filename" or die "Can't open filename: $!";
1 while (<$fh>);
$.
};
print "Total number of lines: $lines\n";
為了有效地計算行數,只需執行以下操作:
int main()
{
unsigned long lines = 0;
int c; /* c must be an int, not char */
while ((c = getchar()) != EOF)
if (c == '\n')
lines++;
printf("%lu\n", lines);
return 0;
} /* main */
我認為在Kernighan&Ritchie中有一個類似的例子,即使不是相同的話。 而且請下次不要使用double
精度數。 使用整數類型進行計數要比使用浮點數進行計數更為有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.