您的位置:首页 > 编程语言 > C语言/C++

Stackoverflow关于C++的Votes最高的一个问答

2014-10-07 19:03 253 查看
觉得挺好玩的,很多大神的回答会让人引起很多思考

先看看源程序

#include "stdafx.h"
#include <algorithm>
#include <ctime>
#include <iostream>

int main()
{
	// Generate data
	const unsigned arraySize = 32768;
	int data[arraySize];

	for (unsigned c = 0; c < arraySize; ++c)
		data[c] = std::rand() % 256;

	// !!! With this, the next loop runs faster
	std::sort(data, data + arraySize);

	// Test
	clock_t start = clock();
	long long sum = 0;
	for (unsigned i = 0; i < 10000; ++i)
	{
		// Primary loop
		for (unsigned c = 0; c < arraySize; ++c)
		{
			if (data[c] >= 128)
				sum += data[c];
		}
	}

	double elapsedTime = static_cast<double>(clock() - start) / CLOCKS_PER_SEC;

	std::cout << elapsedTime << std::endl;
	std::cout << "sum = " << sum << std::endl;
}
然后,对以上程序分别运行两次,第一次不排序,直接计算,第二次排序,在计算。(就是是否注释掉sort那一行的区别)

在我的电脑上,两次运行的结果分别是

排序后



不排序



通过对比我们发现,排序后的执行时间明显降低了。那么是为什呢?

主要的效率差别在这里

if (data[c] >= 128)
	sum += data[c];
对于,底层处理器,每次if判断采用Branch Prediction,分支预测

关于分支预测:http://baike.baidu.com/view/512423.htm?fr=aladdin

对于处理器底层代码,是



分支预测通俗来讲,就是处理器在每次if判断的时候,会根据之前判断的结果进行当前判断的预测,比如之前10次都是true,则先假定当前判断也是true,然后执行。如果发现执行失败,则回退到之前,把本次执行设为false。当数组排序之后,这些假定判断大部分将会成功,也就是说回退的次数会很少。

所以,减少if else是降低分支预测,提高速度的关键

stackflow上给出以下几种解决方式

1、将加法改为位运算,消除分支预测

int t = (data[c] - 128) >> 31;
sum += ~t & data[c];
2、不进行判断

clock_t start = clock();
long long a[] = {0, 0};
long long sum;

for (unsigned i = 0; i < 100000; ++i)
{
    // Primary loop
    for (unsigned c = 0; c < arraySize; ++c)
    {
        int j = (data[c] >> 7);
        a[j] += data[c];
    }
}

double elapsedTime = static_cast<double>(clock() - start) / CLOCKS_PER_SEC;
sum = a[1];


最后,对于这个程序最直接的优化方式

#include "stdafx.h"
#include <algorithm>
#include <ctime>
#include <iostream>

int main()
{
	// Generate data
	const unsigned arraySize = 32768;
	int data[arraySize];

	for (unsigned c = 0; c < arraySize; ++c)
		data[c] = std::rand() % 256;

	// !!! With this, the next loop runs faster
	std::sort(data, data + arraySize);

	// Test
	clock_t start = clock();
	long long sum = 0;
// Primary loop
	for (unsigned c = 0; c < arraySize; ++c)
	{
		if (data[c] >= 128)
			sum += data[c];
	}
	sum = sum*10000;
	double elapsedTime = static_cast<double>(clock() - start) / CLOCKS_PER_SEC;

	std::cout << elapsedTime << std::endl;
	std::cout << "sum = " << sum << std::endl;
}
这样,会将执行的效率提高10000倍

执行的时间和结果



附上

建议去看看,因为确实很多思路很好,本文只是分析了部分

原问题连接:http://stackoverflow.com/questions/11227809/why-is-processing-a-sorted-array-faster-than-an-unsorted-array
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: