ASCII 文字列を整数値に変換する場合、実行しているものよりもはるかに高速になることatoi
はありませんが、インラインで使用する変換関数を実装することで高速化できる場合があります。以下のバージョンでは、スキャンされた数字を超えてポインターがインクリメントされるため、セマンティクスは一致しませんatoi
が、以下に示すように、パーサーの効率を向上させるのに役立つはずです。(エラーチェックは明らかに不足しているので、必要に応じて追加してください。)
static inline int my_parsing_atoi(const char *&s) {
if (s) {
bool neg = false;
int val = 0;
if (*s == '-') { neg = true; ++s; }
for (;isdigit(*s);++s) val = 10*val + (*s - '0');
return neg ? -val : val;
}
return 0;
}
const char *p = input_line;
if (p) {
p += strspn(p, " ");
while (*p) {
int value1 = my_parsing_atoi(p);
p += strspn(p, " ");
}
}
ルーチンが I/O バウンドではなく計算バウンドであることを確認できるように、コードを適切にプロファイリングしたことを確認してください。ほとんどの場合、I/O バウンドになりますが、以下の提案はそれを軽減する方法です。
fread
または などの CまたはC++ ファイル読み取りルーチンを使用している場合、fstream
バッファリングされた読み取りを取得する必要がありますが、これはすでにかなり効率的であるはずですが、 POSIX などの基になる OS 呼び出しを使用してread
、より大きなブロックでファイルを読み取ることができます。一度にファイルの読み取り効率を高速化します。非常に凝った方法として、スレッドを使用するか、aio_read
. . _ mmap
_ munmap
_mmap
上記の解析ルーチンと、次のようなコードを使用して OP のルーチンをベンチマークしました。
clock_t before_real;
clock_t after_real;
struct tms before;
struct tms after;
std::vector<char *> numbers;
make_numbers(numbers);
before_real = times(&before);
for (int i = 0; i < numbers.size(); ++i) {
parse(numbers[i]);
}
after_real = times(&after);
std::cout << "user: " << after.tms_utime - before.tms_utime
<< std::endl;
std::cout << "real: " << after_real - before_real
<< std::endl;
real
との違いuser
はreal
ウォール クロック時間であり、user
は OS がプロセスを実行するのに実際に費やした時間です (したがって、コンテキスト スイッチは実行時間に対してカウントされません)。
私のテストでは、ルーチンが OP のルーチン ( g++ -O3
64 ビット Linux システムでコンパイル) のほぼ 2 倍の速さで実行されました。