操作系统课程实验1-进程调度模拟实验

news2024/9/22 15:39:45

操作系统课程实验1-进程调度模拟实验

一、实验介绍

1.1 实验目的

本实验模拟在单处理机环境下的处理机调度,帮助理解进程调度的概念,深入了解进程控制块的功能,以及进程的创建、撤销和进程各个状态间的转换过程。

1.2 实验内容
  1. 进程调度算法:采用最高优先数优先的调度算法、先来先服务算法、SJF和多级反馈调度算法。
  2. 每个进程有一个进程控制块(PCB)表示。进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。进程的优先数及需要的运行时间可以事先人为输入(也可以由随机数产生)。进程的到达时间为进程输入的时间。 进程的运行时间以时间片为单位进行计算。
1.3 实验要求
  1. 每进行一次调度程序都显示输出一次运行进程、就绪队列、以及各个进程的PCB,以便进行检查。
  2. 对同一组进程的各种调度算法分别计算平均周转时间和平均带权周转时间。
1.4 参考测试数据

系统有5个进程,其就绪时刻、服务时间和优先级(优先级数值越大优先级越高)如下图所示:
在这里插入图片描述

多级反馈队列调度算法:设3个就绪队列,时间片分别为1、2、3。

二、实现代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>

using namespace std;

typedef struct ProcessControlBlock { // 定义进程控制块结构体
	int name;                   // 进程名称
	unsigned int Arrive_Time;   // 到达时间
	unsigned int Wait_Time;     // 等待时间
	unsigned int Start_Time;    // 开始时间
	unsigned int Serve_Time;    // 服务时间
	unsigned int Finish_Time;   // 完成时间
	int Priority;               // 优先级
	unsigned int cycle_time;    // 周转时间
	double Weighted_cycle_time; // 带权周转时间
	unsigned int Original_Serve_Time;
	bool FinishFlag;            // 完成标志
} PCB;                          // 进程控制块的别名

typedef struct Multilevel_Feedback_Queue { // 定义多级反馈队列
	int L1_Length, L1[5];       // 第一级别反馈队列
	int L2_Length, L2[5];       // 第二级别反馈队列
	int L3_Length, L3[5];       // 第三级别反馈队列
	unsigned int Time_Slice[3]; // 三级反馈队列分配的时间片
} MFQ;



void PCB_Info_Input(PCB Process_HPF[5], PCB Process_FCFS[5], PCB Process_SJF[5], PCB Process_MFQ[5]); 					 	// 函数声明:输入进程控制块信息

void Highest_Prioriy_First(PCB  Process[5]); 	// 函数声明:最高优先级优先算法
void First_Come_First_Serve(PCB Process[5]); 	// 函数声明:先来先服务算法
void Shortest_Job_First(PCB Process[5]);	 	// 函数声明:短作业优先算法
void Multilevel_Feedback_Queue_Algorithm(PCB Process[5]);	// 函数声明:多级反馈队列算法
void Multilevel_Feedback_Queue_Algorithm_Input(MFQ * mfq);	// 函数声明:多级反馈队列的输入

bool SortBy_Priority(PCB* a, PCB* b);		 	// 函数声明:按优先级排序
bool SortBy_ServeTime(PCB* a, PCB* b);		 	// 函数声明:按服务时间排序
bool SortBy_ArriveTime(PCB a, PCB b);		 	// 函数声明:按到达时间排序


int main(void) {
	PCB Process_HPF[5]; 								// 定义5个进程控制块数组
	PCB Process_FCFS[5]; 								// 定义5个进程控制块数组
	PCB Process_SJF[5]; 								// 定义5个进程控制块数组
	PCB Process_MFQ[5]; 								// 定义5个进程控制块数组
	PCB_Info_Input(Process_HPF, Process_FCFS, Process_SJF, Process_MFQ); 								// 调用输入进程控制块信息函数
	Highest_Prioriy_First(Process_HPF); 				// 调用优先级最高优先算法函数
	First_Come_First_Serve(Process_FCFS); 				// 调用先来先服务算法函数
	Shortest_Job_First(Process_SJF);	 				// 调用短作业优先算法函数
	Multilevel_Feedback_Queue_Algorithm(Process_MFQ); 	// 调用多级反馈队列调度算法

	return 0;
}

//	3比较函数,用于sort函数的参数
bool SortBy_ArriveTime(PCB a, PCB b) {
	return a.Arrive_Time < b.Arrive_Time;
}
bool SortBy_Priority(PCB* a, PCB* b) {
	return a->Priority < b->Priority;
}
bool SortBy_ServeTime(PCB* a, PCB* b) {
	return a->Serve_Time < b->Serve_Time;
}


void PCB_Info_Input(PCB Process_HPF[5], PCB Process_FCFS[5], PCB Process_SJF[5], PCB Process_MFQ[5]) {
	cout << "\nPlease input the Process Control Block information\n" << endl;
	for (int i = 0; i < 5; i++) {
		printf("PCB%d:", i);
		scanf("%u%u%d", &Process_HPF[i].Arrive_Time, &Process_HPF[i].Serve_Time, &Process_HPF[i].Priority);
		// 完成输入的深拷贝
		Process_FCFS[i].Arrive_Time = Process_SJF[i].Arrive_Time = Process_MFQ[i].Arrive_Time = Process_HPF[i].Arrive_Time;
		Process_FCFS[i].Serve_Time = Process_SJF[i].Serve_Time = Process_MFQ[i].Serve_Time = Process_HPF[i].Serve_Time;
		Process_FCFS[i].Priority = Process_SJF[i].Priority = Process_MFQ[i].Priority = Process_HPF[i].Priority;

		Process_HPF[i].name = Process_FCFS[i].name = Process_SJF[i].name = Process_MFQ[i].name = i + 1; 							// 设置进程名称
		Process_HPF[i].FinishFlag = Process_FCFS[i].FinishFlag = Process_SJF[i].FinishFlag = Process_MFQ[i].FinishFlag = false; 	// 初始化完成标志为false
	}
}

// 优先级最高优先调度算法函数
void Highest_Prioriy_First(PCB Process[5]) {

	cout << "\n优先级最高优先调度算法:" << endl;
	PCB* Available_Processes[5]; 	// 定义指向进程控制块的指针数组
	int FinishCout = 0; 			// 完成进程计数器初始化为0
	unsigned Time = 0; 				// 时间初始化为0
	cout << endl;

	sort(Process, Process + 5, SortBy_ArriveTime);  // 按到达时间对进程数组进行排序
	while (FinishCout < 5) { 						// 当完成进程数量小于5时循环执行调度算法,因为进程还有进程未得到处理机时间
		int j = 0; 									// 已到达且未完成进程计数器初始化为0

		for (int i = 0; i < 5; i++) { 				// 循环遍历所有进程
			if (Process[i].Arrive_Time <= Time and Process[i].FinishFlag == false) { // 如果进程已到达且未完成
				Available_Processes[j++] = Process + i; 							 // 将该进程加入到可用进程数组中
			}
		}

		// 如果j为0,表示当前时间没有到达的进程,此时应该让时间继续推进
		if (j == 0) {
			Time += 1; 	// 时间加1
			continue; 	// 继续下一次循环
		}

		// 将当前时间已经到达的所有进程按优先级进行排序
		sort(Available_Processes, Available_Processes + j, SortBy_Priority);
		// 选取优先级最大的进程执行任务
		Available_Processes[0]->Start_Time = Time; 	// 设置进程开始时间
		Available_Processes[0]->Wait_Time = Available_Processes[0]->Arrive_Time; // 设置进程等待时间
		Time += Available_Processes[0]->Serve_Time; // 更新时间
		Available_Processes[0]->Finish_Time = Time; // 设置进程完成时间
		Available_Processes[0]->cycle_time = Available_Processes[0]->Finish_Time - Available_Processes[0]->Arrive_Time; 	// 计算进程周转时间
		Available_Processes[0]->Weighted_cycle_time = Available_Processes[0]->cycle_time * 1.0 / Available_Processes[0]->Serve_Time;
		Available_Processes[0]->FinishFlag = true; 	// 设置进程完成标志为true
		cout << "PCB:" << Available_Processes[0]->name << "\tArriveTime:" << Available_Processes[0]->Arrive_Time
		     << "\tPriority:" << Available_Processes[0]->Priority
		     << "\tWaitTime:" << Available_Processes[0]->Wait_Time
		     << "\tStartTime:" << Available_Processes[0]->Start_Time
		     << "\tServeTime:" << Available_Processes[0]->Serve_Time
		     << "\tFinishTime:" << Available_Processes[0]->Finish_Time
		     << "\tCircleTime:" << Available_Processes[0]->cycle_time
		     << endl; // 输出进程完成信息
		FinishCout += 1; 							// 完成进程计数器加1
	}
	double avg = 0, weighted_avg = 0;
	for (int i = 0; i < 5; i++) {      // 遍历进程数组
		avg += Process[i].cycle_time;     // 计算总周转时间
		weighted_avg += Process[i].Weighted_cycle_time; // 计算总带权周转时间
	}
	avg /= 5; // 计算平均周转时间
	weighted_avg /= 5; // 计算带权平均周转时间
	cout << "\n平均周转时间:" << avg << endl;          // 输出平均周转时间
	cout << "带权平均周转时间:" << weighted_avg << endl; // 输出带权平均周转时间
}

// 先来先服务调度算法(FCFS)
void First_Come_First_Serve(PCB  Process[5]) {

	cout << "\n先来先服务调度算法:" << endl;
	int FinishCout = 0; 	// 完成进程计数器初始化为0
	unsigned Time = 0; 		// 时间初始化为0
	cout << endl;
	sort(Process, Process + 5, SortBy_ArriveTime); // 按到达时间对进程数组进行排序
	while (FinishCout < 5) { // 当完成进程数量小于5时循环执行调度算法,因为进程还有进程未得到处理机时间
		int j = -1; 		 // 已到达且未完成进程计数器初始化为0

		for (int i = 0; i < 5; i++) { // 循环遍历所有进程
			if (Process[i].Arrive_Time <= Time and Process[i].FinishFlag == false) {
				j = i;
				break;
			}
		}
		// 如果j为-1,表示当前时间没有到达的进程,此时应该让时间继续推进
		if (j == -1) {
			Time += 1; 	// 时间加1
			continue; 	// 继续下一次循环
		}

		// 选取当前满足条件且到达时间最早的进程进行执行
		Process[j].Start_Time = Time; 	// 设置进程开始时间
		Process[j].Wait_Time = Process[j].Start_Time - Process[j].Arrive_Time; // 设置进程等待时间
		Time += Process[j].Serve_Time; 	// 更新时间
		Process[j].Finish_Time = Time; 	// 设置进程完成时间
		Process[j].cycle_time = Process[j].Finish_Time - Process[j].Arrive_Time; 				// 计算进程周转时间
		Process[j].Weighted_cycle_time = Process[j].cycle_time * 1.0 / Process[j].Serve_Time;
		Process[j].FinishFlag = true; 	// 设置进程完成标志为true

		cout << "PCB:" << Process[j].name << "\tArriveTime:" << Process[j].Arrive_Time
		     << "\tWaitTime:" << Process[j].Wait_Time
		     << "\tStartTime:" << Process[j].Start_Time
		     << "\tServeTime:" << Process[j].Serve_Time
		     << "\tFinishTime:" << Process[j].Finish_Time
		     << "\tCircleTime:" << Process[j].cycle_time
		     << endl; // 输出进程完成信息
		FinishCout += 1; // 完成进程计数器加1
	}
	double avg = 0, weighted_avg = 0;
	for (int i = 0; i < 5; i++) {      // 遍历进程数组
		avg += Process[i].cycle_time;     // 计算总周转时间
		weighted_avg += Process[i].Weighted_cycle_time; // 计算总带权周转时间
	}
	avg /= 5; // 计算平均周转时间
	weighted_avg /= 5; // 计算带权平均周转时间
	cout << "\n平均周转时间:" << avg << endl;          // 输出平均周转时间
	cout << "带权平均周转时间:" << weighted_avg << endl; // 输出带权平均周转时间
}

// 短作业优先算法 (SJF)
void Shortest_Job_First(PCB Process[5]) {

	cout << "\n短作业优先算法:" << endl;
	PCB* Available_Processes[5]; 	// 定义指向进程控制块的指针数组
	int FinishCout = 0; 			// 完成进程计数器初始化为0
	unsigned Time = 0; 				// 时间初始化为0
	cout << endl;

	sort(Process, Process + 5, SortBy_ArriveTime); // 按到达时间对进程数组进行排序
	while (FinishCout < 5) { 	// 当完成进程数量小于5时循环执行调度算法,因为进程还有进程未得到处理机时间
		int j = 0; 				// 已到达且未完成进程计数器初始化为0

		for (int i = 0; i < 5; i++) { // 循环遍历所有进程
			if (Process[i].Arrive_Time <= Time and Process[i].FinishFlag == false) { 	// 如果进程已到达且未完成
				Available_Processes[j++] = Process + i; 								// 将该进程加入到可用进程数组中
			}
		}

		// 如果j为0,表示当前时间没有到达的进程,此时应该让时间继续推进
		if (j == 0) {
			Time += 1; 	// 时间加1
			continue; 	// 继续下一次循环
		}

		// 将当前时间已经到达的所有进程按服务时间进行排序
		sort(Available_Processes, Available_Processes + j, SortBy_ServeTime);
		// 选取当前满足条件且服务时间最短的进程执行任务
		Available_Processes[0]->Start_Time = Time; 	// 设置进程开始时间
		Available_Processes[0]->Wait_Time = Available_Processes[0]->Arrive_Time; // 设置进程等待时间
		Time += Available_Processes[0]->Serve_Time; // 更新时间
		Available_Processes[0]->Finish_Time = Time; // 设置进程完成时间
		Available_Processes[0]->cycle_time = Available_Processes[0]->Finish_Time - Available_Processes[0]->Arrive_Time; 	// 计算进程周转时间
		Available_Processes[0]->Weighted_cycle_time = Available_Processes[0]->cycle_time * 1.0 / Available_Processes[0]->Serve_Time;
		Available_Processes[0]->FinishFlag = true; 	// 设置进程完成标志为true
		cout << "PCB:" << Available_Processes[0]->name << "\tArriveTime:" << Available_Processes[0]->Arrive_Time
		     << "\tWaitTime:" << Available_Processes[0]->Wait_Time
		     << "\tStartTime:" << Available_Processes[0]->Start_Time
		     << "\tServeTime:" << Available_Processes[0]->Serve_Time
		     << "\tFinishTime:" << Available_Processes[0]->Finish_Time
		     << "\tCircleTime:" << Available_Processes[0]->cycle_time
		     << endl; // 输出进程完成信息
		FinishCout += 1; 							// 完成进程计数器加1
	}
	double avg = 0, weighted_avg = 0;
	for (int i = 0; i < 5; i++) {      // 遍历进程数组
		avg += Process[i].cycle_time;     // 计算总周转时间
		weighted_avg += Process[i].Weighted_cycle_time; // 计算总带权周转时间
	}
	avg /= 5; // 计算平均周转时间
	weighted_avg /= 5; // 计算带权平均周转时间
	cout << "\n平均周转时间:" << avg << endl;          // 输出平均周转时间
	cout << "带权平均周转时间:" << weighted_avg << endl; // 输出带权平均周转时间

}

void Multilevel_Feedback_Queue_Algorithm(PCB Process[5]) {
	cout << "\n多级反馈队列调度算法:" << endl;
	MFQ MFQSet;
	Multilevel_Feedback_Queue_Algorithm_Input(&MFQSet); // 调用输入多级反馈队列的函数
	queue<PCB> L1, L2, L3; // 定义三个队列
	sort(Process, Process + 5, SortBy_ArriveTime); // 按到达时间对进程数组进行排序
	unsigned int Time = 0; // 时间初始化为0
	double avg = 0, weighted_avg = 0; // 初始化平均周转时间和带权平均周转时间
	for (int i = 0; i < 5; i++) { // 将进程按照到达时间加入到第一级别队列
		Process[i].Original_Serve_Time = Process[i].Serve_Time;
		L1.push(Process[i]);

	}
	while (!L1.empty() || !L2.empty() || !L3.empty()) { // 当三个队列有不为空的时循环
		cout << "Time:" << Time << " \t\t"; // 输出当前时间
		if (!L1.empty()) { // 如果第一级别队列不为空
			PCB temp = L1.front(); // 获取队首进程
			L1.pop();              // 弹出队首进程
			cout << "P" << temp.name << " is processing:"; // 输出当前处理的进程名称
			Time += min(temp.Serve_Time, MFQSet.Time_Slice[0]); // 时间增加当前进程的服务时间或者时间片长度中较小的那个
			temp.Serve_Time = max(0, (int)(temp.Serve_Time - MFQSet.Time_Slice[0])); // 更新当前进程的服务时间
			if (temp.Serve_Time == 0) { // 如果当前进程的服务时间为0
				temp.Finish_Time = Time; // 设置当前进程的完成时间
				temp.cycle_time = temp.Finish_Time - temp.Arrive_Time;   // 计算当前进程的周转时间
				temp.Weighted_cycle_time = (double)temp.cycle_time / temp.Original_Serve_Time; // 计算当前进程的带权周转时间
				avg += temp.cycle_time;     // 计算总周转时间
				weighted_avg += temp.Weighted_cycle_time; // 计算总带权周转时间
				cout << "Finish Time:" << Time << endl; // 输出当前进程的完成时间
			} else {
				cout << 'P' << temp.name << "转移到队列2的末尾\n";
				L2.push(temp); // 否则将当前进程加入到第二级别队列
			}
		} else if (!L2.empty()) { // 如果第一级别队列为空但第二级别队列不为空
			PCB temp = L2.front(); // 获取队首进程
			L2.pop();              // 弹出队首进程
			cout << "P" << temp.name << " is processing:"; // 输出当前处理的进程名称
			Time += min(temp.Serve_Time, MFQSet.Time_Slice[1]); // 时间增加当前进程的服务时间或者时间片长度中较小的那个
			temp.Serve_Time = max(0, (int)(temp.Serve_Time - MFQSet.Time_Slice[1])); // 更新当前进程的服务时间
			if (temp.Serve_Time == 0) { // 如果当前进程的服务时间为0
				temp.Finish_Time = Time; // 设置当前进程的完成时间
				temp.cycle_time = temp.Finish_Time - temp.Arrive_Time;   // 计算当前进程的周转时间
				temp.Weighted_cycle_time = (double)temp.cycle_time / temp.Original_Serve_Time; // 计算当前进程的带权周转时间
				avg += temp.cycle_time;     // 计算总周转时间
				weighted_avg += temp.Weighted_cycle_time; // 计算总带权周转时间
				cout << "Finish Time:" << Time << endl; // 输出当前进程的完成时间
			} else {
				cout << 'P' << temp.name << "转移到队列3的末尾\n";
				L3.push(temp); // 否则将当前进程加入到第三级别队列
			}
		} else { // 如果第一级别和第二级别队列均为空
			while (!L3.empty()) {
				PCB temp = L3.front(); // 获取队首进程
				L3.pop();              // 弹出队首进程
				cout << "P" << temp.name << " is processing:"; // 输出当前处理的进程名称
				Time += min(temp.Serve_Time, MFQSet.Time_Slice[2]); // 时间增加当前进程的服务时间或者时间片长度中较小的那个
				temp.Serve_Time = max(0, (int)(temp.Serve_Time - MFQSet.Time_Slice[2])); // 更新当前进程的服务时间
				if (temp.Serve_Time == 0) { // 如果当前进程的服务时间为0
					temp.Finish_Time = Time; // 设置当前进程的完成时间
					temp.cycle_time = temp.Finish_Time - temp.Arrive_Time;   // 计算当前进程的周转时间
					temp.Weighted_cycle_time = (double)temp.cycle_time / temp.Original_Serve_Time; // 计算当前进程的带权周转时间
					avg += temp.cycle_time;     // 计算总周转时间
					weighted_avg += temp.Weighted_cycle_time; // 计算总带权周转时间
					cout << "Finish Time:" << Time << endl; // 输出当前进程的完成时间
				} else {
					cout << 'P' << temp.name << "继续执行\n";
					L3.push(temp); // 将当前进程加入到第三级别队列末尾
				}
			}
		}
	}
	avg /= 5; // 计算平均周转时间
	weighted_avg /= 5; // 计算带权平均周转时间
	cout << "\n平均周转时间:" << avg << endl;          // 输出平均周转时间
	cout << "带权平均周转时间:" << weighted_avg << endl; // 输出带权平均周转
}



// 输入多级反馈队列的函数
void Multilevel_Feedback_Queue_Algorithm_Input(MFQ *mfq) {
	cout << "Please input the Time Slice(Three Numbers) for Multilevel Feedback Queue" << endl;
	cin >> mfq->Time_Slice[0] >> mfq->Time_Slice[1] >> mfq->Time_Slice[2];
}

三、心灵的救赎

  1. “爱”就是科学与逻辑永远无法解释的程序
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1696388.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

当HR问你是否单身时,该怎么回答?

知识星球&#xff08;星球名&#xff1a;芯片制造与封测技术社区&#xff0c;星球号&#xff1a;63559049&#xff09;里的学员问&#xff1a;我是晶圆厂厂务工程师&#xff0c;最近在面试新工作&#xff0c;但是几乎每家HR都会问我同一个问题&#xff1a;你结婚没有&#xff1…

专业的力量:在自己的领域成为专家

专业的力量:在自己的领域成为专家 我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 现在稀缺的已不再是信息资源&#xff0c;而是运用信息的能力。过去的海…

【全开源】场馆预定系统源码(ThinkPHP+FastAdmin+UniApp)

一款基于ThinkPHPFastAdminUniApp开发的多场馆场地预定小程序&#xff0c;提供运动场馆运营解决方案&#xff0c;适用于体育馆、羽毛球馆、兵乒球馆、篮球馆、网球馆等场馆。 场馆预定系统源码&#xff1a;打造高效便捷的预定体验 一、引言&#xff1a;数字化预定时代的来临 …

计算机毕业设计Python+Spark+PyTroch游戏推荐系统 游戏可视化 游戏爬虫 神经网络混合CF推荐算法 协同过滤推荐算法 steam 大数据

毕业设计&#xff08;论文&#xff09; 基于SpringBoot的游戏防沉迷系统的设计与实现 摘 要 随着网络游戏市场的持续火爆,其最明显的负面影响----“网络游戏沉迷问题”已成为当前社会普遍关心的热点问题。根据2010年8月1日实施的《网络游戏管理暂行办法》&#xff0c;网络游…

记忆力和人才测评,如何提升记忆力?

什么是记忆力&#xff1f; 如何通俗意义上的记忆力&#xff1f;我们可以把人的经历、经验理解成为一部纪录片&#xff0c;那么已经过去发生的事情&#xff0c;就是影片之前的情节&#xff0c;对于这些信息&#xff0c;在脑海里&#xff0c;人们会将其进行处理和组合&#xff…

如何关闭或者减少屏蔽 CloudFlare 的真人检测

经常浏览境外网站的应该常碰到一个真人检测的提示(如下图所示)。最近,明月就收到了一个知乎上的付费咨询:问我如何去掉这个提示,由此明月也特别的研究了一下这个“真人检测”,这算是 CloudFlare 的一个特色了,基本上大家看到站点访问有这个提示的几乎都是用了 CloudFlar…

vue3 ts问题 找不到模块“@/views/home/index.vue”或其相应的类型声明。

1. 找不到模块“/views/HomeView.vue”或其相应的类型声明 今天帮同事看了一个问题&#xff0c;他尝试用vitevue3tspinia创建项目&#xff0c;结果刚上来就遇到这么一个问题 2. 解决办法 出现这个问题的原因就是&#xff1a;ts只支持导出导入模块&#xff0c;但是vue不是模块…

CRMEB开源商城标准版系统前端技术架构与实践探索

摘要&#xff1a; 随着电子商务的蓬勃发展&#xff0c;开源商城系统因其灵活性、可扩展性和成本效益受到了广泛关注。本文以CRMEB开源商城系统为例&#xff0c;探讨了其前端技术架构、开发实践及未来展望。通过对CRMEB系统前端技术的深入分析&#xff0c;旨在为开发者提供有价值…

最大子矩阵+01矩阵

最大子矩阵 题目 思路 确定一个矩阵中的子矩阵&#xff0c;只需要确定矩阵对角线上两点的坐标即可&#xff0c; 在确定了子矩阵之后&#xff0c;还需要计算子矩阵中各元素之和&#xff0c;如果按照常规的循环方法来解决&#xff0c;时间复杂度是O(N^6)&#xff0c;对于本题20…

Java——图书管理系统万字详解(附代码)

框架搭建 book包 将书相关的放到book包中&#xff0c;创建一个Book类用来设置书的属性&#xff0c;包括书名、作者、价格、类型、是否被借出等。 以上属性均被private所修饰 利用编译器生成构造方法&#xff08;不需要构造isBorrowed&#xff0c;因为其初始值为false&#…

2024年5月大语言模型论文推荐:模型优化、缩放到推理、基准测试和增强性能

前一篇文章总结了关于计算机视觉方面的论文&#xff0c;这篇文章将要总结了2024年5月发表的一些最重要的大语言模型的论文。这些论文涵盖了塑造下一代语言模型的各种主题&#xff0c;从模型优化和缩放到推理、基准测试和增强性能。 大型语言模型(llm)发展迅速&#xff0c;跟上…

8个图神经网络的典型用例

虽然 ChatGPT 或 Diffusion 模型等 AI 系统最近备受关注&#xff0c;但图神经网络 (GNN) 却发展迅速。在过去的几年中&#xff0c;GNN 悄然成为众多激动人心的新成就背后的黑马&#xff0c;这些成就从纯学术研究突破一路发展到大规模积极部署的实际解决方案。 Uber、谷歌、阿里…

idea configuration 配置 方便本地启动环境切换

idea 再项目启动的时候避免切换环境导致上线的时候出现环境配置问题 可以再idea 的 configuration 中配置项目的 vm options 虚拟机的内容占用 -Xmx256m -Xms256m -Xmn100m -Xss256k program arguments properties 文件中需要修改的配置参数 active profiles 指定启动的本…

快速幂求逆元与逆元

我上一篇博客链接写的是多个数求乘法逆元而快速幂求逆元用于单个数求乘法逆元 逆元是对分数取模用的 对于除法取模不成立&#xff0c;即(a/b)%p≠(a%p/b%p)%p。求逆元的思路&#xff1a;(一般ACM的题目都是对1e97这种素数取模&#xff0c;所以gcd(a,p)1)a*b1(mod p) > b1/a…

毕设 大数据校园卡数据分析

文章目录 0 前言1 课题介绍2 数据预处理2.1 数据清洗2.2 数据规约 3 模型建立和分析3.1 不同专业、性别的学生与消费能力的关系3.2 消费时间的特征分析 4 Web系统效果展示5 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设…

STM32F1之OV7725摄像头·像素数据输出时序、FIFO 读写时序以及摄像头的驱动原理详解

STM32F1之OV7725摄像头-CSDN博客 STM32F1之I2C通信-CSDN博客 目录 1. 像素数据输出时序 2. FIFO 读写时序 2.1 写时序 2.2 读时序 3. 摄像头的驱动原理 1. 像素数据输出时序 主控器控制 OV7725 时采用 SCCB 协议读写其寄存器&#xff0c;而它输出图像时则使用 VGA 或…

【Linux signal】

Linux signal 一、信号分类二、什么是信号集&#xff1f;三、信号的3个处理过程3.1 发送信号3.1.1 向自身发送信号(raise)3.1.2 向别的进程发送信号(kill)3.1.3 发送闹钟信号(alarm) 3.2 接收(注册)信号3.3 处理信号 在Linux操作系统中&#xff0c;SIGUSR1和SIGUSR2是用户定义的…

仅需一块 4GB 的 GPU ,就能运行开源大语言模型:Llama3 70B

最强的开源大语言模型 Llama3 已经发布一段时间了&#xff0c;一些盆友资源有限&#xff0c;私信询问是否可以使用 4GB 的 VRAM 在本地运行 Llama3 70B。 与 GPT-4 相比&#xff0c;Llama3 的性能如何&#xff1f;Llama3 使用了哪些关键的前沿技术使其变得如此强大&#xff1f…

CIM模型

CIM 是 Esri 制图信息模型。 它是一个地图内容规范,用于记录在保存、读取、引用或打开时如何永久保留描述不同项目组件的信息。 该规范以 JSON 表示,适用于 ArcGIS 应用程序和 API 中的地图、场景、布局、图层、符号和样式。 CIM 不仅限于制图设置。 要了解属性的组织方式以及…

【C++题解】1699 - 输出是2的倍数,但非3的倍数的数

问题&#xff1a;1699 - 输出是2的倍数&#xff0c;但非3的倍数的数 类型&#xff1a;循环 题目描述&#xff1a; 请从键盘读入一个整数 n&#xff0c;输出 1∼n 中所有是 2 的倍数&#xff0c;但非 3 的倍数的数&#xff0c;每行 1个。 比如&#xff0c;读入一个整数10 &…