LLVM Clang 在 OS X 上产生极其缓慢的 input/output
LLVM Clang produces extremely slow input/output on OS X
问:是否可以在 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 秒这一可悲的事实外,它比 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)
。 clang
s 从自制软件(3.7 和 3.8)安装也会产生缓慢的 io。 clang
安装在 Ubuntu (3.8) 上生成快速 io。 Apple LLVM version 8.0.0
生成慢 io(2 人问)。
我也对其进行了一些拆解 (sudo dtruss -c "./test_io gen | ./test_io read"
),发现 clang 版本进行了 2686 write_nocancel
次系统调用,而 gcc 版本进行了 2079 writev
次系统调用。这可能指出了问题的根源。
问题出在未实现 sync_with_stdio.
的 libc++ 中
你的命令行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
问:是否可以在 OS X:
下使用 LLVM Clang 改进此代码的 IOtest_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 秒这一可悲的事实外,它比 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)
。 clang
s 从自制软件(3.7 和 3.8)安装也会产生缓慢的 io。 clang
安装在 Ubuntu (3.8) 上生成快速 io。 Apple LLVM version 8.0.0
生成慢 io(2 人问)。
我也对其进行了一些拆解 (sudo dtruss -c "./test_io gen | ./test_io read"
),发现 clang 版本进行了 2686 write_nocancel
次系统调用,而 gcc 版本进行了 2079 writev
次系统调用。这可能指出了问题的根源。
问题出在未实现 sync_with_stdio.
的 libc++ 中你的命令行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