为什么此基准代码用于线性和二进制搜索不起作用
Why is this benchmark code for linear and binary search not working?
我试图将线性和二进制搜索作为分配的一部分进行基准测试。我已经写了必要的搜索和随机器功能。但是,当我尝试对它们进行基准测试时,即使对于更高的数组尺寸,我也会得到0延迟。
代码:
#include<iostream>
#include <time.h>
#include <windows.h>
using namespace std;
double getTime()
{
LARGE_INTEGER t, f;
QueryPerformanceCounter(&t);
QueryPerformanceFrequency(&f);
return (double)t.QuadPart/(double)f.QuadPart;
}
int linearSearch(int arr[], int len,int target){
int resultIndex = -1;
for(int i = 0;i<len;i++){
if(arr[i] == target){
resultIndex = i;
break;
}
}
return resultIndex;
}
void badSort(int arr[],int len){
for(int i = 0 ; i< len;i++){
int indexToSwapWith = i;
for(int j = i+1;j < len;j++){
if(arr[j] < arr[indexToSwapWith] )
indexToSwapWith = j;
}
if(indexToSwapWith != i){
int t = arr[i];
arr[i] = arr[indexToSwapWith];
arr[indexToSwapWith] = t;
}
}
}
int binSearch(int arr[], int len,int target){
int resultIndex = -1;
int first = 0;
int last = len;
int mid = first;
while(first <= last){
mid = (first + last)/2;
if(target < arr[mid])
last = mid-1;
else if(target > arr[mid])
first = mid+1;
else
break;
}
if(arr[mid] == target)
resultIndex = mid;
return resultIndex;
}
void fillArrRandomly(int arr[],int len){
srand(time(NULL));
for(int i = 0 ; i < len ;i++){
arr[i] = rand();
}
}
void benchmarkRandomly(int len){
float startTime = getTime();
int arr[len];
fillArrRandomly(arr,len);
badSort(arr,len);
/*
for(auto i : arr)
cout<<i<<"n";
*/
float endTime = getTime();
float timeElapsed = endTime - startTime;
cout<< "prep took " << timeElapsed<<endl;
int target = rand();
startTime = getTime();
int result = linearSearch(arr,len,target);
endTime = getTime();
timeElapsed = endTime - startTime;
cout<<"linear search result for "<<target<<":"<<result<<" after "<<startTime<<" to "<<endTime <<":"<<timeElapsed<<"n";
startTime = getTime();
result = binSearch(arr,len,target);
endTime = getTime();
timeElapsed = endTime - startTime;
cout<<"binary search result for "<<target<<":"<<result<<" after "<<startTime<<" to "<<endTime <<":"<<timeElapsed<<"n";
}
int main(){
benchmarkRandomly(30000);
}
样本输出:
PREP取0.9375
701950到701950之后的29445:26987的线性搜索结果:0
二进制搜索结果29445:26987 701950至701950:0
我也尝试使用clock_t,但结果是相同的。我需要更高的数组大小还是我以错误的方式进行基准测试?
在课程中,我必须自己实施大多数东西。这就是为什么我不使用STL。我不确定是否允许使用STL :: Chrono,但我想确保问题不在其他地方。
编辑:如果不清楚,我不能在基准中包括时间和随机生成的时间。
一个问题是,在用随机值打包测试数组之前,请设置starttime = getTime((。如果随机数生成很慢,则可能主导返回结果。主要的工作是对您的数组进行排序,与此相比,搜索时间将非常低。正如您所建议的那样,这可能是一个间隔。对于在30k对象上进行二进制搜索,我们只谈论12或13个迭代,因此在现代机器上最多最多最多20/1000000000秒。这大约为零ms。
增加数组条目的数量无济于事,但是您可以尝试增加数组大小,直到获得接近内存限制为止。但是现在您的问题将是准备的随机数生成和排序将永远花费。
我建议: -
a。检查大量项目: -
unsigned int total;
startTime = getTime();
for (i=0; i<10000000; i++)
total += binSearch(arr, len, rand());
endTime = getTime();
b。修改代码以计算您比较元素的次数并使用该信息而不是计时。
看起来您正在使用搜索结果(通过在定时区域外用cout
*打印它,这很好(。数据 密钥是随机的,因此在编译时不应将搜索优化。(禁用优化的基准测试是毫无意义的,因此您需要这样的技巧。(
您是否使用调试器看了timeElapsed
?也许这是一个很小的float
,用默认cout
设置为0
?
或 float endTime
- float startTime
实际上等于0.0f
,因为舍入到最近的float
使它们等于。减去附近的两个大型浮点数会产生"灾难性的取消"。
请记住,float
只有24位的显着性,因此,无论您除以频率如何,如果performancecounter值在2^24中的少于1的零件差异,则您将获得零。(如果该函数从x86 rdtsc
返回原始计数,那么如果您的系统的最后一次重新启动比时间间隔长2^24倍以上。最后〜10年(以"参考频率"计数(大约(等于您的CPU的额定/"贴纸"频率,而不论涡轮或空闲时钟速度如何。请参阅获得CPU周期计数?(
double
可能会有所帮助,但在除法之前,在整数域中减去>。另外,重写该部分将从定时间隔中取出QueryPerformanceFrequency
!
正如@Jon所建议的那样,通常最好将代码放入一个较长的定时间隔内重复循环,因此(代码(缓存和分支预测可以热身。
,但是您有一个问题,即确保重复调用不会优化,并在循环中随机化搜索键。(否则,聪明的编译器可能会将搜索提高到循环中(。
诸如volatile int result = binSearch(...);
之类的东西可以提供帮助,因为将volatile
分配给(或初始化(是一个可见的副作用,无法优化。因此,编译器需要在寄存器中实际实现每个搜索结果。
对于某些编译器,例如支持GNU C内联ASM的人,您可以使用内联ASM要求编译器在寄存器中产生一个值,而无需添加任何在任何地方存储它的开销。Afaik使用MSVC Inline ASM不可能。
- 有根的二进制搜索树.保留与其父级的链接
- cpp二进制搜索问题,计算给定数组中输入元素的出现次数
- 二进制搜索树叶数问题
- 为什么二进制搜索在我的测试中不起作用
- 正在尝试重载二进制搜索树分配运算符
- 我的二进制搜索程序只是关闭了
- 二进制搜索的终止点
- 递归二进制搜索与字符串数组
- 测试树是否为二进制搜索树
- 如何二进制搜索结构向量并在适当的索引处插入
- 如果你有一个固定大小的数组,你需要遍历它!n次,使用二进制搜索如何改变时间复杂性
- 字符串的递归二进制搜索-C++
- 使用二进制搜索树中的迭代器对象访问左侧节点
- 二进制搜索树没有匹配的函数调用
- 二进制搜索不适用于特定输出
- 如何在向量上进行二进制搜索以找到具有特定id的元素
- 二进制搜索树不变的标头文件
- 二进制搜索树插入带参数参考
- 二进制搜索不变以查找元素的首次出现
- 了解一种神秘地起作用的递归二进制搜索算法