我知道这段代码是如何工作的,但我找不到为什么这段代码比其他i / o方法更快?
int read_int() {
char c = getchar_unlocked();
while(c<'0' || c>'9') c = getchar_unlocked();
int ret = 0;
while(c>='0' && c<='9') {
ret = 10 * ret + c - 48;
c = getchar_unlocked();
}
return ret;
}
答案 0 :(得分:1)
scanf("%d\n", &x)
必须解析格式字符串并在读取之前和之后锁定流。
std::cin >> x
也可能会锁定,并且可能需要与stdin
同步,并且可能需要经历一些抽象层。
通过上述方法,您只需要进行一种类型的输入解析(因此无需解析格式字符串并根据该解析确定要执行的操作),最重要的是,您不会锁定流。
POSIX要求锁定流,glibc使用递归互斥锁来防止多个线程(即使在单线程环境中)同时访问stdin FILE
(这会破坏它)。
这些互斥锁非常昂贵(read_int
应该比scanf("%d",&x)
快几倍(fivish?)。
关于你的实施,除了解决幻数问题,
您可能也应该检测getchar_unlocked
中的失败并通过单独的通道报告这些失败 - 例如,通过传入的指针返回解析的整数并使用返回状态进行错误报告。
如果您想要线程安全,您仍然可以使用getchar_unlocked
获得与getchar
相比的加速,但您必须在开头和结尾flockfile(stdin);
和funlock(stdin);
(分别)你的read_int
函数。
答案 1 :(得分:1)
线程之间的锁定很昂贵。这是一个非锁定IO调用。
https://discuss.codechef.com/questions/2667/getchar_unlocked