[英]boost::dynamic_bitset slower than std::bitset unless std::bitset is reset
我最近遇到了位集模板,並非常想在我的當前項目中使用它們。 繼續閱讀,我看到std::bitset
模板必須具有在編譯時確定的大小。 許多人建議使用boost::dynamic_bitset
減輕此要求。
為了比較兩者,我決定對set
, flip
和count
方法進行速度比較。
結果很奇怪……我想知道是否有人可以為我闡明一下。
代碼在帖子的結尾,但是我將在這里解釋我在做什么。 我有一個std::bitset
對象(稱為bs
)和一個boost::dynamic_bitset
對象(稱為dynbs
)。 每個都有n=1000000
位。 對於上面給定的方法,依次對n
位中的每個位調用該方法,並重復此R=10000
次。
使用std::chrono
庫,以下是每個std::chrono
的時間(以納秒為單位):
set
bitset: 267 nsecs
dyn bitset: 18603174546 nsecs
flip
bitset: 73 nsecs
dyn bitset: 18842352867 nsecs
count
bitset: 77 nsecs
dyn bitset: 51 nsecs
對於set
和flip
, boost::dynamic_bitset
似乎要慢得多。
更有趣的是,如果在運行這些測試之前在兩個對象上調用了reset
方法,那么時間是可比的。 他們來了:
set
bitset: 19397779399 nsecs
dyn bitset: 18472863864 nsecs
flip
bitset: 18599248629 nsecs
dyn bitset: 18376267939 nsecs
count
bitset: 68 nsecs
dyn bitset: 61 nsecs
現在,兩個容器都聲稱將所有位初始化為0
,因此調用reset
不應更改任何位。 reset
前后none
轉儲none
的輸出會確認這一點。
所以畢竟,我有兩個問題:
1)為什么在調用set
和flip
時boost::dynamic_bitset
比std::bitset
慢得多?
2)為什么調用reset
對std::bitset
的速度有巨大的負面影響?
這是我的代碼:
#include <iostream>
#include <iomanip>
#include <bitset>
#include <boost/dynamic_bitset.hpp>
#include <vector>
#include <chrono>
#include <ctime>
using namespace std;
using namespace chrono;
using namespace boost;
int main(){
const unsigned int n=1000000;
bitset< n > bs;
dynamic_bitset< > dynbs(n);
// bs.reset();
// dynbs.reset();
unsigned int i,r,R=10000;
high_resolution_clock::time_point tick,tock;
////////////////////////////////////////////////////////////
// Method: set
std::cout << "set" << std::endl;
tick=high_resolution_clock::now();
for(r=0; r<R; r++)
for(i=0; i<n; i++)
bs.set(i);
tock=high_resolution_clock::now();
cout << setw(16) << "bitset: "
<< setw(16) << duration_cast<nanoseconds>(tock-tick).count() << " nsecs"
<< std::endl;
tick=high_resolution_clock::now();
for(r=0; r<R; r++)
for(i=0; i<n; i++)
dynbs.set(i);
tock=high_resolution_clock::now();
cout << setw(16) << "dyn bitset: "
<< setw(16) << duration_cast<nanoseconds>(tock-tick).count() << " nsecs"
<< std::endl << std::endl;
////////////////////////////////////////////////////////////
// Method: flip
std::cout << "flip" << std::endl;
tick=high_resolution_clock::now();
for(r=0; r<R; r++)
for(i=0; i<n; i++)
bs.flip(i);
tock=high_resolution_clock::now();
cout << setw(16) << "bitset: "
<< setw(16) << duration_cast<nanoseconds>(tock-tick).count() << " nsecs"
<< std::endl;
tick=high_resolution_clock::now();
for(r=0; r<R; r++)
for(i=0; i<n; i++)
dynbs.flip(i);
tock=high_resolution_clock::now();
cout << setw(16) << "dyn bitset: "
<< setw(16) << duration_cast<nanoseconds>(tock-tick).count() << " nsecs"
<< std::endl << std::endl;
////////////////////////////////////////////////////////////
// Method: count
std::cout << "count" << std::endl;
tick=high_resolution_clock::now();
for(r=0; r<R; r++)
for(i=0; i<n; i++)
bs.count();
tock=high_resolution_clock::now();
cout << setw(16) << "bitset: "
<< setw(16) << duration_cast<nanoseconds>(tock-tick).count() << " nsecs"
<< std::endl;
tick=high_resolution_clock::now();
for(r=0; r<R; r++)
for(i=0; i<n; i++)
dynbs.count();
tock=high_resolution_clock::now();
cout << setw(16) << "dyn bitset: "
<< setw(16) << duration_cast<nanoseconds>(tock-tick).count() << " nsecs"
<< std::endl;
return 0;
}
我用
g++ -O3 -std=c++11 bitset.cpp -o bitset
其中bitset.cpp
是上面插入的代碼。
1)為什么在調用set和flip時
boost::dynamic_bitset
比std::bitset
慢得多?
由於std::bitset
不使用動態分配,並且您的bitset
是局部變量,因此編譯器可以輕松確定所有set
和flip
以及count
都沒有外部可見的效果。 結果,它優化了它們 ,並且您的代碼基本上最終成為一堆計時和打印調用。
請注意,在上述程序集中,它甚至沒有為該位集分配堆棧空間。 整個事情基本上消失了無影無蹤。
boost::dynamic_bitset
用new
動態分配其緩沖區,最終調用::operator new()
,后者可以是在不同轉換單元中定義的任意重載版本。 因此,對於編譯器來說,很難證明返回的緩沖區的更改在外部不可見。
std::bitset
和boost::dynamic_bitset
count
循環都已優化,因為編譯器可以輕松地看到count()
不會更改位集中的任何內容,並且您不使用返回值。
2)為什么調用
reset
對std :: bitset的速度有巨大的負面影響?
我檢查了GCC中reset
的源代碼,它調用了編譯器固有的__builtin_memset
,並向其傳遞了指向緩沖區的指針。 當您將指向堆棧變量的指針傳遞給外部函數時,編譯器在可刪除內容方面受到了更大的限制,因為該變量的更改現在可以從外部觀察到(例如,調用的函數可能已經存儲了一個副本)。某個地方的指針,以后便可以窺視它)。
好吧,看來TC有了解釋。
您對位集的所有設置和翻轉(和計數)都已完全優化。
匯編代碼提供了一個鏈接來顯示此內容: 匯編代碼
通過從三種不同方法返回值並將它們添加到其他變量中,就成功了,現在看來似乎是一場公平的戰斗(如TC所建議)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.