现在我们假设要在没排序的数组中找一个数:
菜狗也能写出如下的算法1:
找到了我就返回位置,否则我就返回-1。
int search1(){
for (int i = 0; i < MAXN; ++i){
if (nums[i] == VALUE){
return i;
}
}
return -1;
}
现在问题来了,算法效率差一点点,入股能优化8%那就可以用了,怎么办?
大家也许还记得,比较运算符是非常耗时的,我们如果不用比较运算符,同样的线性算法,也许有可能有些优化,多少呢?
我实现了一下,8%左右问题不大,代码附在后面,search2()。
那万一还不行,依旧是这个算法,我们要做到之前时间的3分之一,怎么办?
别急别急,法子简单的很,就是把++i去掉,把中间的部分手写8次,然后每次i+=8,你还真别不信,我实现之后,耗时只有之前的四分之一左右!!!!!。代码附在后面search3中。
为啥呢?因为将循环展开有助于避免管道阻塞,减少分支,增加指令级的并行性。下面是实验结果:
time1=0.075000
time2=0.069000
优化= 8%
time3=0.021000
优化= 72%
[Finished in 1.4s]
完整代码如下:
#include <iostream>
#include <cstdio>
#include <ctime>
using namespace std;
int nums[51000000];
const int POSITION = 40000000;
const int MAXN = 50000000;
const int VALUE = 2;
int search1();
int search2();
int search3();
clock_t start, end;
int main(){
for (int i = 0; i < MAXN; ++i){
nums[i] = 1;
}
nums[POSITION] = 2;
start = clock();
search1();
end = clock();
double time1 = (double)(end-start)/CLK_TCK;
printf("time=%f\n",(double)(end-start)/CLK_TCK);
start = end = 0;
start = clock();
search2();
end = clock();
double time2 = (double)(end-start)/CLK_TCK;
printf("time=%f\n",(double)(end-start)/CLK_TCK);
cout << (time1 - time2) / time1 * 100 << endl;
start = clock();
search3();
end = clock();
double time3 = (double)(end-start)/CLK_TCK;
printf("time=%f\n",(double)(end-start)/CLK_TCK);
cout << (time1 - time3) / time1 * 100 << endl;
return 0;
}
int search1(){
for (int i = 0; i < MAXN; ++i){
if (nums[i] == VALUE){
return i;
}
}
return -1;
}
int search2(){
int hold = nums[MAXN -1];
nums[MAXN - 1] = INT_MAX;
int i;
for (i = 0; ; i += 1){
if (nums[i] == VALUE){
break;
}
}
nums[MAXN - 1] = hold;
if (i == MAXN - 1){
return -1;
}
return i;
}
int search3(){
int hold = nums[MAXN -1];
nums[MAXN - 1] = INT_MAX;
int i;
for (i = 0; ; i += 8){
if (nums[i] == VALUE){
break;
}
if (nums[i + 1] == VALUE){
i += 1;
break;
}
if (nums[i + 2] == VALUE){
i += 2;
break;
}
if (nums[i + 3] == VALUE){
i += 3;
break;
}
if (nums[i + 4] == VALUE){
i += 4;
break;
}
if (nums[i + 5] == VALUE){
i += 5;
break;
}
if (nums[i + 6] == VALUE){
i += 6;
break;
}
if (nums[i + 7] == VALUE){
i += 7;
break;
}
}
nums[MAXN - 1] = hold;
if (i == MAXN - 1){
return -1;
}
return i;
}