Rất nhiều ở đây phụ thuộc vào số lượng giá trị Boolean bạn đang làm việc.
Cả hai bitet và vector<bool>
thường sử dụng biểu diễn được đóng gói trong đó Boolean được lưu trữ chỉ như một bit.
Một mặt, áp đặt một số chi phí ở dạng thao tác bit để truy cập một giá trị duy nhất.
Mặt khác, điều đó cũng có nghĩa là nhiều Booleans của bạn sẽ phù hợp với bộ nhớ cache của bạn.
Nếu bạn đang sử dụng nhiều Booleans (ví dụ, triển khai rây Eratosthenes), hãy lắp nhiều bộ nhớ trong bộ nhớ cache hầu như sẽ luôn có kết quả thuần. Việc giảm sử dụng bộ nhớ sẽ giúp bạn có được nhiều hơn thao tác bit bị mất.
Hầu hết các đối số chống lại std::vector<bool>
quay trở lại thực tế rằng nó không phải là vùng chứa tiêu chuẩn (nghĩa là nó không đáp ứng các yêu cầu đối với vùng chứa). IMO, đây chủ yếu là câu hỏi về kỳ vọng - vì nó nói vector
, nhiều người cho rằng đó là một container (các loại vectơ khác), và chúng thường phản ứng tiêu cực với thực tế là vector<bool>
không phải là vùng chứa.
Nếu bạn đang sử dụng vectơ theo cách thực sự yêu cầu nó là một vùng chứa, thì có thể bạn muốn sử dụng một số kết hợp khác - deque<bool>
hoặc vector<char>
có thể hoạt động tốt. Hãy suy nghĩ trước khi bạn làm điều đó mặc dù - có rất nhiều (lousy, IMO) khuyên rằng vector<bool>
nên tránh nói chung, với ít hoặc không có giải thích lý do tại sao nó nên tránh ở tất cả, hoặc trong những trường hợp nó làm cho một thực tế sự khác biệt với bạn.
Có, có những tình huống mà một thứ khác sẽ hoạt động tốt hơn. Nếu bạn đang ở trong một trong những tình huống đó, sử dụng một cái gì đó khác rõ ràng là một ý tưởng tốt. Nhưng, hãy chắc chắn rằng bạn đang thực sự trong một trong những tình huống đầu tiên. Bất cứ ai nói với bạn (ví dụ) rằng "Herb nói rằng bạn nên sử dụng vector<char>
" mà không có nhiều lời giải thích về sự cân bằng liên quan nên không đáng tin cậy.
Hãy đưa ra một ví dụ thực tế. Vì nó đã được đề cập trong các ý kiến, chúng ta hãy xem xét các Sieve of Eratosthenes:
#include <vector>
#include <iostream>
#include <iterator>
#include <chrono>
unsigned long primes = 0;
template <class bool_t>
unsigned long sieve(unsigned max) {
std::vector<bool_t> sieve(max, false);
sieve[0] = sieve[1] = true;
for (int i = 2; i < max; i++) {
if (!sieve[i]) {
++primes;
for (int temp = 2 * i; temp < max; temp += i)
sieve[temp] = true;
}
}
return primes;
}
// Warning: auto return type will fail with older compilers
// Fine with g++ 5.1 and VC++ 2015 though.
//
template <class F>
auto timer(F f, int max) {
auto start = std::chrono::high_resolution_clock::now();
primes += f(max);
auto stop = std::chrono::high_resolution_clock::now();
return stop - start;
}
int main() {
using namespace std::chrono;
unsigned number = 100000000;
auto using_bool = timer(sieve<bool>, number);
auto using_char = timer(sieve<char>, number);
std::cout << "ignore: " << primes << "\n";
std::cout << "Time using bool: " << duration_cast<milliseconds>(using_bool).count() << "\n";
std::cout << "Time using char: " << duration_cast<milliseconds>(using_char).count() << "\n";
}
Chúng tôi đã sử dụng một mảng đủ lớn mà chúng ta có thể mong đợi một phần lớn của nó để chiếm bộ nhớ chính. Tôi cũng đã đi đến một chút đau đớn để đảm bảo rằng chỉ điều thay đổi giữa một lời gọi và người kia là việc sử dụng một số vector<char>
và vector<bool>
. Đây là một số kết quả. Đầu tiên với VC++ 2015:
ignore: 34568730
Time using bool: 2623
Time using char: 3108
... thì thời gian sử dụng g ++ 5.1:
ignore: 34568730
Time using bool: 2359
Time using char: 3116
Rõ ràng, vector<bool>
thắng trong cả hai trường hợp - bằng khoảng 15% với VC++, và hơn 30% với gcc. Cũng lưu ý rằng trong trường hợp này, tôi đã chọn kích thước để hiển thị vector<char>
trong ánh sáng khá thuận lợi. Nếu, ví dụ, tôi giảm number
100000000
-10000000
, sự khác biệt thời gian trở nên nhiều lớn:
ignore: 3987474
Time using bool: 72
Time using char: 249
Mặc dù tôi đã không được thực hiện rất nhiều công việc để xác nhận, tôi đoán rằng trong trường hợp này , phiên bản sử dụng vector<bool>
sẽ tiết kiệm đủ không gian mà mảng phù hợp hoàn toàn trong bộ nhớ cache, trong khi vector<char>
đủ lớn để tràn bộ nhớ cache và liên quan đến rất nhiều quyền truy cập bộ nhớ chính.
Vì nó phụ thuộc vào cách bạn sử dụng nó, kích thước tương đối của vùng chứa và bộ đệm CPU của bạn, và có thể là các yếu tố khác ... những gì đã xảy ra khi bạn đánh giá nó? – Useless