C++ 多线程归并排序尝试

#if __cplusplus < 201103L
#error This file requires compiler and library support for the \
ISO C++ 2011 standard. This support is currently experimental, and must be \
enabled with the -std=c++11 or -std=gnu++11 compiler options. /// 这段话来自,<c++0x_warning.h>  
#endif

//#pragma GCC optimize(2) /// O2 优化 

#include <iostream>
#include <ctime>
#include <thread> /// C++ 11 标准的多线程写法 
#include <algorithm>
using namespace std;

int NOT_THREAD = (980); /// 多大长度一下不开启新线程 

const int maxn = 1000000 + 7;
int A[maxn], B[maxn];
void thread_merge_sort(int L, int R) { /// 多线程归并排序 
	if(L >= R) return;
	if(R - L == 1) {
		if(A[L] > A[R]) swap(A[L], A[R]); /// 区间中只有两个数的情况 
	}else {
		int mid = (L + R) >> 1;
		if(R - L >= NOT_THREAD) {
			thread Lth(thread_merge_sort, L,   mid);
			thread_merge_sort(mid + 1, R); /// 右半部分直接在当前线程排序 
			Lth.join();
		}else {
			thread_merge_sort(L,   mid);
			thread_merge_sort(mid+1, R); /// 直接递归计算,不建立新的线程 
		}
		int l = L, r = mid+1, m = L;
		while(l <= mid && r <= R) {
			if(A[l] <= A[r]) B[m ++] = A[l ++];
			else             B[m ++] = A[r ++];
		}
		while(l <= mid) B[m ++] = A[l ++];
		while(r <= R  ) B[m ++] = A[r ++];
		for(int i = L; i <= R; i ++) A[i] = B[i];
	}
}

int rand(int L, int R) {
	int RND = rand(); /// linux 下直接使用 rand() 生成随机数即可 
	#ifdef _WIN64
		RND = (rand() << 15) | RND;
	#endif
	#ifdef _WIN32
		RND = (rand() << 15) | RND;
	#endif
	return RND % (R - L + 1) + L;
}

class timer { /// 计时器 
	private:
		long long time_begin;
	public:
		timer(bool auto_begin = true) { /// 默认自动开始计时 
			if(auto_begin) {
				time_begin = clock();
			}
		}
		void begin() {
			time_begin = clock(); /// 开始计时 
		}
		double time_now() {
			return (clock() - time_begin)/(CLOCKS_PER_SEC * 1.0); /// 计算当前时刻 
		}
};

void Check(bool use_threads = true) {
	printf(use_threads ? "=> Threads\t[ available ]\n" : "=> Threads\t[unavailable]\n");
	printf(
		#ifdef _WIN64
			"-> _WIN64\t[ availalbe ]\n" /// 编译器 win64 环境 
		#endif
		#ifdef _WIN32
			"-> _WIN32\t[ available ]\n" /// 编译器 win32 环境 
		#endif
			"-> default\t[ available ]\n"
	);
	ios::sync_with_stdio(false); /// 关闭同步 
	int n = 1000000;
	for(int i = 1; i <= n; i ++) A[i] = rand(1, 1000000000); /// 输入被排序的序列 
	if(!use_threads) NOT_THREAD = 0x7fffffff; /// 不适用多线程 
	timer Timer; 
	thread_merge_sort(1, n); /// 多线程归并排序 
	printf("=> n = %d, Timer: %.3lf sec\n\n\n", n, Timer.time_now());
}

int main() {
	Check( true); /// 使用多线程 
	Check(false); /// 不使用多线程 
	return 0;
}

本地运行结果

可以看到,多线程归并排序比直接使用归并排序快了 31.25 % 31.25\% 31.25%(因 CPU 而异)。

O2优化后的效果对比图

开启 -O2 优化前后,多线程归并排序算法的运行效率提升并不显著,但是普通归并排序的效果有显著提升。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 归并排序是一种经典的排序算法,它的核心思想是将待排序的数组不断拆分成两个子数组,直到拆分为只包含一个元素的子数组,然后再将这些子数组合并成一个有序的数组。 在归并排序排序阶段,可以利用多线程的特性进行并行处理。当需要将数组拆分成两个子数组时,可以同时创建两个线程来处理这两个子数组的排序操作。这样可以减少排序的时间复杂度,提高整体的排序速度。 在归并排序归并阶段,同样可以利用多线程来进行并行处理。当需要将两个有序的子数组合并时,可以创建多个线程来同时处理这些子数组的合并操作。这样可以将整个归并过程分成多个小任务,各个线程独立地进行合并操作,最后再将结果合并成一个有序的数组。 通过在排序阶段和归并阶段都使用多线程,可以充分利用计算机的多核处理器并行处理能力,加快归并排序的执行速度。但是需要注意的是,多线程并不总是能够带来性能的提升,需要合理地调度线程和任务,避免线程之间的竞争和冲突,才能发挥出多线程的优势。 综上所述,归并排序排序阶段和归并阶段都可以使用多线程来提高排序效率,但需要注意线程之间的协调和调度,使得多线程能够充分发挥优势,最终得到正确的排序结果。 ### 回答2: 归并排序是一种经典的排序算法,可以通过多线程来提高其执行效率。在排序阶段和归并阶段都可以使用多线程来进行加速。 在排序阶段,归并排序将待排序的序列分成两个子序列,然后对这两个子序列进行排序。如果使用多线程,可以将分治算法中的分解操作交给不同的线程来处理。每个线程负责对一个子序列进行排序,从而同时进行多个子序列的排序。这样可以大大缩短排序时间,提高效率。 在归并阶段,归并排序将已排序的子序列进行合并。同样可以使用多线程来加速合并操作。可以将待合并的子序列分成多个部分,每个线程负责合并其中的一部分。通过并行地合并多个子序列,可以有效地减少合并时间。 需要注意的是,在多线程的情况下,需要合理地划分任务和数据,实现合理的负载均衡。如果划分不当,可能导致线程之间的竞争和同步开销,反而影响排序效率。因此,在实际应用中,需要综合考虑硬件环境、任务规模和数据分布等因素,来确定最适合的多线程策略。 总之,归并排序可以利用多线程在排序阶段和归并阶段进行并行计算,从而提高算法的执行效率。合理的多线程策略可以充分利用硬件资源,加速排序过程,提高排序效率。 ### 回答3: 归并排序是一种排序算法,通过将待排序的数组分成两个子数组,对每个子数组进行排序,然后再将已排序的子数组通过归并操作合并成一个有序的数组。在排序阶段和归并阶段都可以使用多线程来加速排序过程。 在排序阶段,可以将原始数组平均分成多个子数组,每个子数组由一个线程来排序。因为归并排序是递归算法,可以将排序过程按照树状结构分解成多个小任务,每个线程负责处理一个任务。在处理每个任务时,线程可以独立对该子数组进行排序,不需要等待其他线程的结果,从而提高排序效率。 在归并阶段,多个已排序的子数组可以并行地进行归并操作。可以使用多个线程将已排序的子数组两两归并成更大的有序子数组,然后再将这些有序子数组两两归并,直到最终得到一个完全有序的数组。多个线程可以并行地执行归并操作,每个线程独立负责一部分子数组的归并,而不需要等待其他线程的结果,从而加快整个数组的归并速度。 通过在排序阶段和归并阶段都使用多线程,归并排序可以充分利用多核处理器的计算能力,提高排序的速度。然而,使用多线程也需要注意线程间的同步和数据访问冲突问题,以及线程的创建和销毁开销等。因此,在实际应用中,需要综合考虑算法的复杂度和数据规模,选择合适的线程数以及线程的任务分配策略,以达到最佳的排序性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值