2012-03-17 48 views
12

我爲各種編程奧林匹克編碼,因此爲了提高時間效率,我正在尋找獲取輸入的最快方法,而無需添加額外的庫,即在標準可用目錄內每個gcc編譯器,因爲在比賽期間,我們顯然不能將庫添加到編譯器中。直到現在我用C++,我用cin和cout,但發現scanf和printf比它快得多,所以任何人都可以告訴我更快的方法,這可能是一個自定義函數,因爲我不介意空間的複雜性,但我更喜歡時間。 先進的謝謝。哪個是C++中輸入速度最快的方法

+2

您是否在尋找實現時間或運行時間?對於運行時,您可能會對我的答案感興趣:http://stackoverflow.com/a/8854366/365496 – bames53 2012-03-17 05:08:08

+0

在比賽中不常見的文件嗎?光纖通道SAN驅動器使它們真的*快速:) – 2012-03-17 05:10:01

回答

16

這些流總是比C-API函數慢是一個相當常見的誤解,因爲默認情況下它們與C層同步。所以是的,這是一個功能,而不是一個錯誤。

不犧牲類型安全(和可讀性,取決於你的口味),你可能通過獲得與流的性能:

std::ios_base::sync_with_stdio (false); 

一個小指示燈:

#include <cstdio> 
#include <iostream> 

template <typename Test> 
void test (Test t) 
{ 
    const clock_t begin = clock(); 
    t(); 
    const clock_t end = clock(); 
    std::cout << (end-begin)/double(CLOCKS_PER_SEC) << " sec\n"; 
} 

void std_io() { 
    std::string line; 
    unsigned dependency_var = 0; 

    while (!feof (stdin)) { 
     int c; 
     line.clear(); 
     while (EOF != (c = fgetc(stdin)) && c!='\n') 
      line.push_back (c); 
     dependency_var += line.size(); 
    } 

    std::cout << dependency_var << '\n'; 
} 

void synced() { 
    std::ios_base::sync_with_stdio (true); 
    std::string line; 
    unsigned dependency_var = 0; 
    while (getline (std::cin, line)) { 
     dependency_var += line.size(); 
    } 
    std::cout << dependency_var << '\n'; 
} 

void unsynced() { 
    std::ios_base::sync_with_stdio (false); 
    std::string line; 
    unsigned dependency_var = 0; 
    while (getline (std::cin, line)) { 
     dependency_var += line.size(); 
    } 
    std::cout << dependency_var << '\n'; 
} 

void usage() { std::cout << "one of (synced|unsynced|stdio), pls\n"; } 

int main (int argc, char *argv[]) { 
    if (argc < 2) { usage(); return 1; } 

    if (std::string(argv[1]) == "synced") test (synced); 
    else if (std::string(argv[1]) == "unsynced") test (unsynced); 
    else if (std::string(argv[1]) == "stdio") test (std_io); 
    else { usage(); return 1; } 

    return 0; 
} 

與G ++ -O3和一個大文本文件:

cat testfile | ./a.out stdio 
... 
0.34 sec 

cat testfile | ./a.out synced 
... 
1.31 sec 

cat testfile | ./a.out unsynced 
... 
0.08 sec 

這是如何適用於您的案件取決於。修改此玩具基準測試,添加更多測試,並比較例如std::cin >> a >> b >> cscanf ("%d %d %d", &a, &b, &c);。我保證,通過優化(即不處於調試模式),性能差異將會微妙。

如果這樣不能滿足您的需求,您可以嘗試其他方法,例如,首先閱讀整個文件(可能會或可能不會帶來更多性能)或內存映射(這是一種非便攜式解決方案,但大型桌面具有它們)。


更新

格式的輸入:scanf函數與流

#include <cstdio> 
#include <iostream> 

template <typename Test> 
void test (Test t) 
{ 
    const clock_t begin = clock(); 
    t(); 
    const clock_t end = clock(); 
    std::cout << (end-begin)/double(CLOCKS_PER_SEC) << " sec\n"; 
} 

void scanf_() { 
    char x,y,c; 
    unsigned dependency_var = 0; 

    while (!feof (stdin)) { 
     scanf ("%c%c%c", &x, &y, &c); 
     dependency_var += x + y + c; 
    } 

    std::cout << dependency_var << '\n'; 
} 

void unsynced() { 
    std::ios_base::sync_with_stdio (false); 
    char x,y,c; 
    unsigned dependency_var = 0; 
    while (std::cin) { 
     std::cin >> x >> y >> c; 
     dependency_var += x + y + c; 
    } 
    std::cout << dependency_var << '\n'; 
} 

void usage() { std::cout << "one of (scanf|unsynced), pls\n"; } 

int main (int argc, char *argv[]) { 
    if (argc < 2) { usage(); return 1; } 

    if (std::string(argv[1]) == "scanf") test (scanf_); 
    else if (std::string(argv[1]) == "unsynced") test (unsynced); 
    else { usage(); return 1; } 

    return 0; 
} 

結果:

scanf: 0.63 sec 
unsynced stream: 0.41 
+3

流比C-API慢,但有一個原因(它做了很多工作)。它具有內置在讀者/作者中的所有Locale東西,這些東西在C-API中並不存在,並且這可能很昂貴(儘管嘗試並使用「C」語言環境(但它仍然存在)將其最小化)。這裏我們評論假設我們使用格式化輸入/輸出而不是直接讀/寫。 – 2012-03-17 06:24:14

+0

@LokiAstari:不一定。 scanf總是要求解析格式字符串,而對於流,它不會在運行時出現。 – 2012-03-17 06:36:09

+0

@LokiAstari:提供格式化輸入的示例。在第一次閱讀時忽略它(對不起):C-io也使用語言環境(http://linux.die.net/man/3/setlocale)。 – 2012-03-17 06:46:18

0

可能scanf比使用流有點快。雖然流提供了很多類型安全性,並且不必在運行時解析格式化字符串,但它通常具有不需要過多內存分配的優點(這取決於您的編譯器和運行時)。這就是說,除非性能是你唯一的最終目標,並且你處在關鍵路徑中,那麼你應該真正喜歡更安全(更慢)的方法。

有由香草薩特寫在這裏很美味的文章

http://www.gotw.ca/publications/mill19.htm

誰進入了很多字符串格式化喜歡的sscanf和lexical_cast的,什麼樣的東西表現的細節都讓他們跑了緩慢或快速。這有點類似,可能是那些會影響C風格IO和C++風格之間性能的東西。與格式化程序的主要區別在於類型安全性和內存分配數量。

+0

請注意,默認情況下,流與C-API同步。如果您禁用同步,則流將通常比C-API快或有時更快。 – 2012-03-17 05:59:52

5

通常,緩衝輸入將是最快的。你不得不刷新輸入緩衝區的頻率越高,輸入就越快。有關完整且非常豐富的討論,請參閱this question。簡而言之,read()具有較大的緩衝區大小,因爲它幾乎直接在操作系統中的相應系統調用的頂部。

相關問題