LLVM Clang在OS X上产生极慢的输入/输出

3

问:在OS X上,使用LLVM Clang是否可能提高此代码的IO性能:

test_io.cpp:

#include <iostream>
#include <string>

constexpr int SIZE = 1000*1000;

int main(int argc, const char * argv[]) {
  std::ios_base::sync_with_stdio(false);
  std::cin.tie(nullptr);

  std::string command(argv[1]);
  if (command == "gen") {
    for (int i = 0; i < SIZE; ++i) {
      std::cout << 1000*1000*1000 << " ";
    }
  } else if (command == "read") {
    int x;
    for (int i = 0; i < SIZE; ++i) {
      std::cin >> x;
    }
  }
}

编译:

clang++ -x c++ -lstdc++ -std=c++11 -O2 test_io.cpp -o test_io

基准测试:

> time ./test_io gen | ./test_io read

real    0m2.961s
user    0m3.675s
sys     0m0.012s

除了读取10MB文件需要3秒钟这个令人沮丧的事实外,它比通过Homebrew安装的g++要慢得多:

> gcc-6 -x c++ -lstdc++ -std=c++11 -O2 test_io.cpp -o test_io
> time ./test_io gen | ./test_io read

real    0m0.149s
user    0m0.167s
sys     0m0.040s

我的 clang 版本是 Apple LLVM version 7.0.0 (clang-700.0.72)。从 homebrew 安装的 clang(3.7 和 3.8)也会产生缓慢的 IO。在 Ubuntu 上安装的 clang(3.8)生成快速 IO。但是,Apple LLVM version 8.0.0 会导致 IO 缓慢(有两个人问过)。我对其进行了一些 dtruss 测试(sudo dtruss -c "./test_io gen | ./test_io read"),发现 clang 版本会执行 2686 次 write_nocancel 系统调用,而 gcc 版本则会执行 2079 次 writev 系统调用。这可能指向问题的根源。

相关问题:http://stackoverflow.com/questions/38624468/clang-fstreams-10x-slower-than-g - Danh
你尝试过使用 -O3 吗? - Danh
如果你将clang编译版本的输出输入到gcc编译版本中,它仍然非常快,但是如果你将gcc编译版本的输出输入到clang编译版本中,速度就会变慢 - 因此我推断是clang阅读速度较慢。如果您将输出字符从空格更改为“X”,它们都很快,速度大致相同。 - Mark Setchell
1个回答

3
问题出在libc++中没有实现sync_with_stdio。
您的命令行clang++ -x c++ -lstdc++ -std=c++11 -O2 test_io.cpp -o test_io未使用libstdc ++,而是将使用libc ++。要强制使用libstdc ++,您需要-stdlib=libstdc++
如果您已准备好输入文件,则最小示例为:
int main(int argc, const char * argv[]) {
    std::ios_base::sync_with_stdio(false);
    int x;
    for (int i = 0; i < SIZE; ++i) {
      std::cin >> x;
    }
}

时间:

$ clang++ test_io.cpp -o test -O2 -std=c++11  
$  time ./test read < input
real    0m2.802s
user    0m2.780s
sys 0m0.015s
$ clang++ test_io.cpp -o test -O2 -std=c++11  -stdlib=libstdc++
clang: warning: libstdc++ is deprecated; move to libc++
$  time ./test read < input
real    0m0.185s
user    0m0.169s
sys 0m0.012s

sync_with_stdio的lib ++实现位于[src / ios.cpp](http://llvm.org/svn/llvm-project/libcxx/trunk/src/ios.cpp)的末尾。正如Joky所说,这是一个无操作。 - Alan Green

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接