两个CPU核分配任务问题


    两个CPU核分配任务问题:

    给定n(0~N)个任务work,每个任务i=0~n-1都有各自需要处理的时间needTime[i] =1~1000(ms)。另外有两个CPU核(核A、核B)处理这些任务,将n个任务分配给两个CPU核,求这两个核处理完所有给定任务所需要的最短时间。

其中,每个任务只能分配给一个核进行处理,且只被能处理一次。每个CPU核同一时间只能处理一个任务。

例如,输入needTime[5] = {5,5,5,7,7};五个任务,分配结果是5+5+5=15(ms),7+7=14(ms),最终输出15。两个CPU核在15ms内处理完所有任务。


    解决思路:首先随机设计一种“任务分配方案”,然后再不断交换两个核内分配的某些任务,使结果不断优化,直至得到最优解,最后输出结果。该思路来源于《算法导论》第26章最大流的增广路径的反方向调度的思想。

    具体过程:首先随机得到一种分配方案——核A:5+7=12,核B:5+5+7=17。核B - 核A = 5,寻找在核B中的某任务的需求时间b 与 核A中的某任务的需求时间a,满足 0 < b-a < 核B - 核A。目前,核B中有个任务的需求时间为 7 ,核A中的有个任务的需求时间为 5 ,7-5=2 < 核B - 核A,交换核A和核B的这两个任务,得到一种更优的新的任务分配方案,核A:7+7=14,核B:5+5+5=15。此时,核B - 核A = 1,在核B中的所有任务 与 核A中的所有任务,无法满足 0 < b-a < 核B - 核A,停止寻找,输出15。

    停止的判断条件,即获得最优解的条件,是无法在核A中的所有任务 与 核B中的所有任务 中找到满足“ 0 < a-b < 核A - 核B ”或“ 0 < b-a < 核B - 核A ”。这个结论用一句话来证明:如果  在核A中的所有任务 与 核B中的所有任务 中找到满足“ 0 < a-b < 核A - 核B ”或“ 0 < b-a < 核B - 核A ”的情况,当前的分配方案一定可以通过交换两个任务得到更优的分配方案。:设a==0或b==0的任务为“空任务”,我们认为“空任务”,也是可交换的任务,核A和核B中都有无数个“空任务”。


int func(vector<int> &nums) 
{
	nums.push_back(0);// 添加 执行时间为 0 的任务,为了便于求单个任务的执行时间
	int len = nums.size();
	quickSort(nums, 0, len - 1);// 快速排序,从小到大
	unordered_map<int, vector<pair<int, int> > > mapping;// 声明一个 hashmap,用于存储两个任务的差
	for (size_t fir = 0; fir < len; fir++)
		for (size_t sec = fir + 1; sec < len; sec++)
			mapping[nums[sec] - nums[fir]].push_back(pair<int, int>(fir, sec));// 存储两个任务的差,其中 second >= first,即 second 任务执行时间 不少于 first 任务执行时间

	int t_A = 0, t_B = 0;// 记录各CPU的当前总执行时间
	vector<int> mark;// 声明一个标记,用来标记任务的分配情况
	mark.push_back(0);// 第一个执行时间为 0 的任务,不分配,标记为 0
	for (int i = 1; i < len / 2; i++) 
	{
		mark.push_back(1);// 分配给CPU-A,标记为 1
		t_A += nums[i];
	}
	for (int i = len / 2; i < len; i++) 
	{
		mark.push_back(-1);// 分配给CPU-B,标记为 -1
		t_B += nums[i];
	}
	int d_t = abs(t_A - t_B);// 两个CPU的总执行时间的差
	const int s_t = t_A + t_B;// 两个CPU的总执行时间的和
	int flag = 1;// 增广方案 是否存在的标记,1 表示存在,0 表示不存在

	// 不断寻找两个CPU的增广方案,当找不到增广方案时 flag == 0,说明达到最优解,停止while循环
	while (flag) 
	{
		flag = 0;
		for (int t = d_t - 1; t > 0; t--) 
		{
			if (mapping.find(t) == mapping.end()) continue;// 没有 ==t 的增广方案,进行下一步 t-1 的增广方案的寻找
			const auto& vec = mapping[t];
			for (int k = 0; k < vec.size(); k++) 
			{
				// 存在 ==t 的增广方案,并且该方案中 first == 0,只有一个任务,且该任务在总执行时间较大的CPU的分组中
				if (vec[k].first == 0 
					&& mark[vec[k].second] * (t_A - t_B) > 0) 
				{
					mark[vec[k].second] *= -1;// 转移该任务的分组
					t_A += mark[vec[k].second] * nums[vec[k].second];
					t_B = s_t - t_A;
					flag = 1;// 找到增广方案,设置为 1
					break;
				}
				// 存在 ==t 的增广方案,执行时间较大的任务 在总执行时间较大的CPU的分组中,且执行时间较小的任务 在总执行时间较小的CPU的分组中,交换这两个任务
				if (vec[k].first != 0 
					&& mark[vec[k].second] * (t_A - t_B) > 0 
					&& mark[vec[k].first] * mark[vec[k].second] == -1) 
				{
					mark[vec[k].first] *= -1;// 转移该任务的分组
					mark[vec[k].second] *= -1;// 转移该任务的分组
					t_A += mark[vec[k].first] * nums[vec[k].first];
					t_A += mark[vec[k].second] * nums[vec[k].second];
					t_B = s_t - t_A;
					flag = 1;// 找到增广方案,设置为 1
					break;
				}
			}
			if (flag == 1) break;// 找到增广方案
		}
		d_t = abs(t_A - t_B);// 重新计算 两个CPU的总执行时间的差
	}

	return (t_A > t_B) ? t_A : t_B;
}









  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面我会详细说明关于移植UCOSIII时遇到HardFault_Handler错误的解决方法。 首先,需要了解UCOSIII和HAL库的中断优先级设置方式。UCOSIII是通过设置全局中断优先级分组和中断优先级来管理中断的。可以在OSInit()函数中设置中断优先级分组和中断优先级,如下所示: ``` OS_ERR os_err; CPU_IntInit(); // 初始化CPU中断 os_err = OS_ERR_NONE; #if OS_CFG_APP_HOOKS_EN > 0u OS_AppInitHook(); // APP初始化钩子函数 #endif OS_CPU_SR_ALLOC(); // 定义CPU状态寄存器 OS_ENTER_CRITICAL(); // 进入临界区 // 设置中断分组 NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); // 设置中断优先级 NVIC_SetPriority(USART1_IRQn, 1); // 设置USART1中断优先级为1 NVIC_SetPriority(DMA2_Stream2_IRQn, 2); // 设置DMA2_Stream2中断优先级为2 OS_EXIT_CRITICAL(); // 退出临界区 os_err = OSInit(); // 初始化UCOSIII内 ``` 而HAL库中的中断优先级设置是通过NVIC_SetPriority()函数来实现的。例如: ``` HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); // 设置USART1中断优先级为0,子优先级为0 HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 1); // 设置DMA2_Stream2中断优先级为0,子优先级为1 ``` 在移植UCOSIII时,需要将HAL库中的中断优先级设置为与UCOSIII中的中断优先级相同,以保证两者之间的一致性。 其次,需要注意中断优先级分组的设置。UCOSIII默认使用NVIC_PRIORITYGROUP_4中断优先级分组,因此在OSInit()函数中也要设置为NVIC_PRIORITYGROUP_4。 最后,需要确保所有的中断优先级都被正确地设置。如果中断优先级没有被正确地设置,可能会导致HardFault_Handler错误。可以通过以下方法来检查中断优先级是否设置正确: 1. 在代码中添加断言语句,检查中断优先级是否在正确的范围内。例如: ``` assert_param(IS_NVIC_PRIORITY_VALID(USART1_IRQn, 1)); // 检查USART1中断优先级是否在0-15之间 assert_param(IS_NVIC_PRIORITY_VALID(DMA2_Stream2_IRQn, 2)); // 检查DMA2_Stream2中断优先级是否在0-15之间 ``` 2. 在调试器中查看中断优先级是否正确。可以在调试器中设置断点,在程序执行到OSInit()函数中的NVIC_SetPriority()函数时,查看中断优先级是否正确。 综上所述,移植UCOSIII时遇到HardFault_Handler错误的解决方法是: 1. 在OSInit()函数中设置正确的中断优先级分组和中断优先级,以确保与HAL库的设置一致。 2. 检查中断优先级是否被正确地设置,并在需要的地方添加断言语句或者调试器中查看中断优先级是否正确。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值