《编程珠玑》代码之路14:两个不会算法也能把效率提升4倍的小套路

现在我们假设要在没排序的数组中找一个数:

菜狗也能写出如下的算法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;
}

猜你喜欢

转载自blog.csdn.net/beijixiong5622/article/details/84574272