Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ boost::dynamic_位集比std::位集慢,除非重置std::位集_C++_Boost Dynamic Bitset_Std Bitset - Fatal编程技术网

C++ boost::dynamic_位集比std::位集慢,除非重置std::位集

C++ boost::dynamic_位集比std::位集慢,除非重置std::位集,c++,boost-dynamic-bitset,std-bitset,C++,Boost Dynamic Bitset,Std Bitset,我最近遇到了位集模板,非常想在我当前的项目中使用它们。继续阅读,我发现std::bitset模板必须在编译时确定大小。许多人建议使用boost::dynamic_位集来缓解这一需求 为了比较这两种方法,我决定对set、flip和count方法进行速度比较 结果很奇怪……我想知道是否有人能帮我解释一下 代码在文章的末尾,但我会解释我在这里做什么。我有一个std::bitset对象(称之为bs)和一个boost::dynamic_bitset对象(称之为dynbs)。每个都有n=1000000位。对

我最近遇到了位集模板,非常想在我当前的项目中使用它们。继续阅读,我发现
std::bitset
模板必须在编译时确定大小。许多人建议使用
boost::dynamic_位集
来缓解这一需求

为了比较这两种方法,我决定对
set
flip
count
方法进行速度比较

结果很奇怪……我想知道是否有人能帮我解释一下

代码在文章的末尾,但我会解释我在这里做什么。我有一个
std::bitset
对象(称之为
bs
)和一个
boost::dynamic_bitset
对象(称之为
dynbs
)。每个都有
n=1000000
位。对于上面给定的方法,按顺序调用每个
n
位上的方法,并重复该
R=10000

使用
std::chrono
库,以下是以纳秒为单位的计时:

set
位集:267纳秒
动态位集:18603174546 nsecs
轻弹
位集:73纳秒
动态位集:18842352867 nsecs
计数
比特集:77纳秒
动态位集:51纳秒
boost::dynamic_位集
对于
set
flip
来说似乎要慢得多

为了让它更有趣,如果在运行这些测试之前对两个对象调用了方法
reset
,那么计时是可比较的。这是:

set
位集:19397779399 nsecs
动态位集:18472863864 nsecs
轻弹
位集:18599248629 nsecs
动态位集:18376267939 nsecs
计数
位集:68纳秒
动态位集:61纳秒
现在,两个容器都声明将所有位初始化为
0
,因此调用
reset
不应更改任何位。在
reset
之前和之后转储
none
的输出会确认这一点

所以在这之后,我有两个问题:

1) 为什么调用
set
flip
boost::dynamic_位集
std::位集
慢得多

2) 为什么调用
reset
会对
std::bitset
的速度产生巨大的负面影响

这是我的密码:

#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
使用名称空间计时;
使用名称空间boost;
int main(){
常量无符号整数n=1000000;
位集bs;
动态位集<>dynbs(n);
//重置();
//dynbs.reset();
无符号整数i,r,r=10000;
高分辨率时钟:时间点滴答滴答;
////////////////////////////////////////////////////////////
//方法:集合

std::cout好吧,看起来T.C.有解释

位集上的所有设置和翻转(以及计数)都已完全优化 出去

装配代码中提供了一个链接,以显示以下内容:

通过返回三种不同方法的值并将它们添加到另一个变量中,成功了,现在看来这是一场公平的斗争(正如T.C.所建议的)

1) 为什么
boost::dynamic_位集
std::bitset
调用set和flip时

由于
std::bitset
不使用动态分配,并且您的
bitset
是一个局部变量,因此编译器可以轻松确定所有
翻转
计数
都没有外部可见的效果。因此,它和您的代码基本上是一堆计时和打印ng打电话来

请注意,在上面的程序集中,它甚至没有为位集分配堆栈空间。整个过程基本上消失得无影无踪

boost::dynamic_bitset
使用
new
动态分配其缓冲区,最终调用
::operator new()
,它可以是在不同翻译单元中定义的任意重载版本。因此,编译器很难证明对返回缓冲区的更改在外部是不可见的

您的
count
循环对于
std::bitset
boost::dynamic_bitset
都进行了优化,因为编译器可以很容易地看到
count()
不会更改位集中的任何内容,并且您也不会使用返回值

2) 为什么调用
reset
会对移动速度产生巨大的负面影响 位集


我在GCC中检查了
reset
的源代码,它调用了一个编译器内部
\uuuu builtin\u memset
,将一个指向缓冲区的指针传递给它。当您将指向堆栈变量的指针传递给外部函数时,编译器在它可以删除的内容上受到了更大的限制,因为变量中的更改现在可能是外部的servable(例如,被调用的函数可能已将指针的副本存储在某个位置,稍后可以从中窥视).

@T.C.那么,是不是我的测试太简单了?我想我不太清楚这意味着什么。我试图阅读汇编代码,但不太明白发生了什么。基本上。微基准很难编写。在这种情况下,如果在每个循环后添加要打印的代码,例如,
bs
,那么
设置
s和
>flip
s可能不会被优化掉。为了确保
count
调用不会被优化掉,请将返回值添加到一个变量中,然后打印出来。
dynamic_bitset
使用堆上的分配,编译器更难证明
set
flip
所做的更改会被优化掉隐形。@T.C.明白了。这很有道理。谢谢你澄清引擎盖下发生的事情。只是添加了一些