C+中的线性搜索与二进制搜索实时性能+; 在使用C++代码-2/P>比较二进制搜索和线性搜索的实时性能时,得到了完全出乎意料的结果。 typedef std::chrono::microseconds us; int linear_search(uint64_t* val, int s, int e, uint64_t k) { while (s < e) { if (!less<uint64_t>()(val[s], k)) { break; } ++s; } return {s}; } int binary_search(uint64_t* val, int s, int e, uint64_t k) { while (s != e) { const int mid = (s + e) >> 1; if (less<uint64_t>()(val[mid], k)) { s = mid + 1; } else { e = mid; } } return {s}; } int main() { // Preparing data int iter = 1000000; int m = 1000; uint64_t val[m]; for(int i = 0; i < m;i++) { val[i] = rand(); } sort(val, val + m); uint64_t key = rand(); // Linear search time computation auto start = std::chrono::system_clock::now(); for (int i = 0; i < iter; i++) { linear_search(val, 0, m - 1, key); } auto end = std::chrono::system_clock::now(); auto elapsed_us = std::chrono::duration_cast<us>(end - start); std::cout << "Linear search: " << m << " values " << elapsed_us.count() << "us\n"; // Binary search time computation start = std::chrono::system_clock::now(); for (int i = 0; i < iter; i++) { binary_search(val, 0, m - 1, key); } end = std::chrono::system_clock::now(); elapsed_us = std::chrono::duration_cast<us>(end - start); std::cout << "Binary search: " << m <<" values " << elapsed_us.count() << "us\n"; }
当使用-O3优化进行编译时,获取此输出-C+中的线性搜索与二进制搜索实时性能+; 在使用C++代码-2/P>比较二进制搜索和线性搜索的实时性能时,得到了完全出乎意料的结果。 typedef std::chrono::microseconds us; int linear_search(uint64_t* val, int s, int e, uint64_t k) { while (s < e) { if (!less<uint64_t>()(val[s], k)) { break; } ++s; } return {s}; } int binary_search(uint64_t* val, int s, int e, uint64_t k) { while (s != e) { const int mid = (s + e) >> 1; if (less<uint64_t>()(val[mid], k)) { s = mid + 1; } else { e = mid; } } return {s}; } int main() { // Preparing data int iter = 1000000; int m = 1000; uint64_t val[m]; for(int i = 0; i < m;i++) { val[i] = rand(); } sort(val, val + m); uint64_t key = rand(); // Linear search time computation auto start = std::chrono::system_clock::now(); for (int i = 0; i < iter; i++) { linear_search(val, 0, m - 1, key); } auto end = std::chrono::system_clock::now(); auto elapsed_us = std::chrono::duration_cast<us>(end - start); std::cout << "Linear search: " << m << " values " << elapsed_us.count() << "us\n"; // Binary search time computation start = std::chrono::system_clock::now(); for (int i = 0; i < iter; i++) { binary_search(val, 0, m - 1, key); } end = std::chrono::system_clock::now(); elapsed_us = std::chrono::duration_cast<us>(end - start); std::cout << "Binary search: " << m <<" values " << elapsed_us.count() << "us\n"; },c++,compiler-optimization,binary-search,linear-search,C++,Compiler Optimization,Binary Search,Linear Search,当使用-O3优化进行编译时,获取此输出- Linear search: 1000 values 0us Binary search: 1000 values 13424us 我知道,对于较小的数组大小,二进制搜索可能比线性搜索昂贵,但无法通过添加-O3来理解这种大小差异的原因。编译器设法意识到线性搜索是一个noop(没有副作用),并将其转换为不做任何事。所以它不需要时间 要修复这个问题,考虑返回值并添加它,然后在时序块之外打印它。 < P>编译器设法实现线性搜索是NOOP(它没有副作用),并将
Linear search: 1000 values 0us
Binary search: 1000 values 13424us
我知道,对于较小的数组大小,二进制搜索可能比线性搜索昂贵,但无法通过添加-O3来理解这种大小差异的原因。编译器设法意识到线性搜索是一个noop(没有副作用),并将其转换为不做任何事。所以它不需要时间
要修复这个问题,考虑返回值并添加它,然后在时序块之外打印它。
< P>编译器设法实现线性搜索是NOOP(它没有副作用),并将其转换为无所作为。所以它不需要时间要修复这个问题,考虑返回值并加起来,然后将它打印到计时块之外。
< p>我对代码进行了基准测试,二进制搜索快得多(对于<代码> m=100 < /代码>,它被破解为<代码> m=1000 < /代码>)。这是我的基准代码:int linear_search(uint64_t* val, int s, int e, uint64_t k) {
while (s < e) {
if (!std::less<uint64_t>()(val[s], k)) {
break;
}
++s;
}
return s;
}
int binary_search(uint64_t* val, int s, int e, uint64_t k) {
while (s != e) {
const int mid = (s + e) >> 1;
if (std::less<uint64_t>()(val[mid], k)) {
s = mid + 1;
} else {
e = mid;
}
}
return s;
}
constexpr int m = 100;
uint64_t val[m];
uint64_t key = rand();
void init() {
static bool isInitialized = false;
if (isInitialized) return;
for(int i = 0; i < m;i++) {
val[i] = rand();
}
std::sort(val, val + m);
isInitialized = true;
}
static void Linear(benchmark::State& state) {
init();
for (auto _ : state) {
int result = linear_search(val, 0, m - 1, key);
benchmark::DoNotOptimize(result);
}
}
BENCHMARK(Linear);
static void Binary(benchmark::State& state) {
init();
for (auto _ : state) {
int result = binary_search(val, 0, m - 1, key);
benchmark::DoNotOptimize(result);
}
}
BENCHMARK(Binary);
int线性搜索(uint64\u t*val、int s、int e、uint64\u t k){
而(s>1;
if(std::less()(val[mid],k)){
s=mid+1;
}否则{
e=中等;
}
}
返回s;
}
constexpr int m=100;
uint64_t val[m];
uint64_t key=rand();
void init(){
静态布尔值初始化=假;
如果(初始)返回;
for(int i=0;i
结果是:
只有(自动:状态){的
中的代码是基准测试的。我用它对代码进行了基准测试,二进制搜索速度更快(对于m=100
,对于m=1000
),它会中断。这是我的基准测试代码:
int linear_search(uint64_t* val, int s, int e, uint64_t k) {
while (s < e) {
if (!std::less<uint64_t>()(val[s], k)) {
break;
}
++s;
}
return s;
}
int binary_search(uint64_t* val, int s, int e, uint64_t k) {
while (s != e) {
const int mid = (s + e) >> 1;
if (std::less<uint64_t>()(val[mid], k)) {
s = mid + 1;
} else {
e = mid;
}
}
return s;
}
constexpr int m = 100;
uint64_t val[m];
uint64_t key = rand();
void init() {
static bool isInitialized = false;
if (isInitialized) return;
for(int i = 0; i < m;i++) {
val[i] = rand();
}
std::sort(val, val + m);
isInitialized = true;
}
static void Linear(benchmark::State& state) {
init();
for (auto _ : state) {
int result = linear_search(val, 0, m - 1, key);
benchmark::DoNotOptimize(result);
}
}
BENCHMARK(Linear);
static void Binary(benchmark::State& state) {
init();
for (auto _ : state) {
int result = binary_search(val, 0, m - 1, key);
benchmark::DoNotOptimize(result);
}
}
BENCHMARK(Binary);
int线性搜索(uint64\u t*val、int s、int e、uint64\u t k){
而(s>1;
if(std::less()(val[mid],k)){
s=mid+1;
}否则{
e=中等;
}
}
返回s;
}
constexpr int m=100;
uint64_t val[m];
uint64_t key=rand();
void init(){
静态布尔值初始化=假;
如果(初始)返回;
for(int i=0;i
结果是:
仅用于(自动:状态)的内的代码{
已经过基准测试。优化了,对输出做些什么,这样编译器就不会完全跳过块。如果您没有使用线性搜索的结果,那么当优化打开时,编译器会删除该部分。令人困惑的是,为什么二进制搜索部分没有发生同样的情况,我建议您使用ts您可以看到生成的汇编代码以了解发生了什么。@最大的_prime_是_463035818 val由指针获取,如果变量在后面引用,编译器不能排除副作用,二进制搜索是最后一个,后面没有对val的引用。@AlessandroTeruzzi是的,但不是。编译器确实优化了线性搜索
首先,两者都使用指针。一旦它优化了linear\u search
,它就可以删除binary\u search
优化了,对输出执行一些操作,这样编译器就不会完全跳过块。你没有使用线性搜索的结果,因此编译器会在执行优化时删除该部分更令人困惑的是,为什么我推荐的二进制搜索部分没有出现同样的情况,它让您可以查看生成的汇编代码以了解发生了什么。@最大的\u prime\u是\u 463035818 val是指针获取的,如果变量在之后被引用,则编译器无法排除副作用,二进制搜索是最后一次,并且没有对v的引用al在后面。@AlessandroTeruzzi是的,但不是。编译器确实优化了linear\u search
,两者都使用指针。一旦它优化了linear\u search
,它还可以删除binary\u search
不知道的基准测试。感谢更新的代码!不知道基准测试。谢谢对于更新的代码!