在http://bit1129.iteye.com/blog/2180214一文中,分析了Hash based shuffle的写过程。其中分析的是,未开始map端产生的数据文件做consolidate的流程,不开启则会创建M*R个文件,如果M和R都很大,比如2000*600,那么120万个小文件的读写将是性能瓶颈,这也是Hadoop采用sort based shuffle以及Spark在1.2的时候,将sort based shuffle作为默认shuffle算法,因为它们产生的输出文件就是确定的R个。
在Hash based shuffle中,Spark通过开启consolidationFiles选项,可以将文件进行consolidation,此时产生的文件个数就是M个
本文分析Spark开启consolidationFiles选项,mapper将文件进行consolidate的原理和过程
1. 总体框架图
上图基本准确
2.实例代码:
package spark.examples.shuffle import org.apache.spark.{SparkConf, SparkContext} import org.apache.spark.SparkContext._ object SparkHashShuffleConsolidationFile { def main(args: Array[String]) { System.setProperty("hadoop.home.dir", "E:\\devsoftware\\hadoop-2.5.2\\hadoop-2.5.2"); val conf = new SparkConf() conf.setAppName("SparkWordCount") conf.setMaster("local") //Hash based Shuffle; conf.set("spark.shuffle.manager", "hash"); //使用文件聚合 conf.set("spark.shuffle.consolidateFiles", "true"); val sc = new SparkContext(conf) //10个以上的分区,每个分区对应一个Map Task //读取一个1M的文件 val rdd = sc.textFile("file:///D:/1.txt", 10); //十个以上的mapper分区 val rdd1 = rdd.flatMap(_.split(" ")) val rdd2 = rdd1.map((_, 1)) val rdd3 = rdd2.reduceByKey(_ + _, 6); ///6个Reducer Task rdd3.saveAsTextFile("file:///D:/wordcount" + System.currentTimeMillis()); println(rdd3.toDebugString) sc.stop } }
2.1 结果产生了六个输出文件:
C:\Users\hadoop\AppData\Local\Temp\spark-local-20150219165442-cf2d>tree /f 文件夹 PATH 列表 卷序列号为 4E9D-390C C:. ├─02 │ merged_shuffle_0_5_0 │ ├─03 │ merged_shuffle_0_4_0 │ ├─04 │ merged_shuffle_0_3_0 │ ├─05 │ merged_shuffle_0_2_0 │ ├─06 │ merged_shuffle_0_1_0 │ ├─07 │ merged_shuffle_0_0_0 │ ├─0c ├─0d ├─0e ├─11 └─13
2.2 将reducer的个数改为8,结果产生了8个输出文件
C:\Users\hadoop\AppData\Local\Temp\spark-local-20150219165701-135d>tree /f 文件夹 PATH 列表 卷序列号为 4E9D-390C C:. ├─00 │ merged_shuffle_0_7_0 │ ├─01 │ merged_shuffle_0_6_0 │ ├─02 │ merged_shuffle_0_5_0 │ ├─03 │ merged_shuffle_0_4_0 │ ├─04 │ merged_shuffle_0_3_0 │ ├─05 │ merged_shuffle_0_2_0 │ ├─06 │ merged_shuffle_0_1_0 │ ├─07 │ merged_shuffle_0_0_0 │ ├─0c ├─0d ├─0e ├─11 └─13
2.3系统内核为4,将mater的local改为local[3],reducer个数仍然为8,结果产生了24个文件
C:\Users\hadoop\AppData\Local\Temp\spark-local-20150219171357-b6b4>tree /f 文件夹 PATH 列表 卷序列号为 4E9D-390C C:. ├─00 │ merged_shuffle_0_5_2 │ merged_shuffle_0_6_1 │ merged_shuffle_0_7_0 │ ├─01 │ merged_shuffle_0_4_2 │ merged_shuffle_0_5_1 │ merged_shuffle_0_6_0 │ ├─02 │ merged_shuffle_0_3_2 │ merged_shuffle_0_4_1 │ merged_shuffle_0_5_0 │ ├─03 │ merged_shuffle_0_2_2 │ merged_shuffle_0_3_1 │ merged_shuffle_0_4_0 │ ├─04 │ merged_shuffle_0_1_2 │ merged_shuffle_0_2_1 │ merged_shuffle_0_3_0 │ ├─05 │ merged_shuffle_0_0_2 │ merged_shuffle_0_1_1 │ merged_shuffle_0_2_0 │ ├─06 │ merged_shuffle_0_0_1 │ merged_shuffle_0_1_0 │ ├─07 │ merged_shuffle_0_0_0 │ ├─0c ├─0d ├─0e ├─11 ├─13 ├─3e │ merged_shuffle_0_7_2 │ └─3f merged_shuffle_0_6_2 merged_shuffle_0_7_1
2.4系统内核为4,将mater的local改为local[6],reducer个数仍然为8,结果产生了48个文件
文件夹 PATH 列表 卷序列号为 4E9D-390C C:. ├─00 │ merged_shuffle_0_2_5 │ merged_shuffle_0_3_4 │ merged_shuffle_0_4_3 │ merged_shuffle_0_5_2 │ merged_shuffle_0_6_1 │ merged_shuffle_0_7_0 │ ├─01 │ merged_shuffle_0_1_5 │ merged_shuffle_0_2_4 │ merged_shuffle_0_3_3 │ merged_shuffle_0_4_2 │ merged_shuffle_0_5_1 │ merged_shuffle_0_6_0 │ ├─02 │ merged_shuffle_0_0_5 │ merged_shuffle_0_1_4 │ merged_shuffle_0_2_3 │ merged_shuffle_0_3_2 │ merged_shuffle_0_4_1 │ merged_shuffle_0_5_0 │ ├─03 │ merged_shuffle_0_0_4 │ merged_shuffle_0_1_3 │ merged_shuffle_0_2_2 │ merged_shuffle_0_3_1 │ merged_shuffle_0_4_0 │ ├─04 │ merged_shuffle_0_0_3 │ merged_shuffle_0_1_2 │ merged_shuffle_0_2_1 │ merged_shuffle_0_3_0 │ ├─05 │ merged_shuffle_0_0_2 │ merged_shuffle_0_1_1 │ merged_shuffle_0_2_0 │ ├─06 │ merged_shuffle_0_0_1 │ merged_shuffle_0_1_0 │ ├─07 │ merged_shuffle_0_0_0 │ ├─0c ├─0d ├─0e ├─11 ├─13 ├─3b │ merged_shuffle_0_7_5 │ ├─3c │ merged_shuffle_0_6_5 │ merged_shuffle_0_7_4 │ ├─3d │ merged_shuffle_0_5_5 │ merged_shuffle_0_6_4 │ merged_shuffle_0_7_3 │ ├─3e │ merged_shuffle_0_4_5 │ merged_shuffle_0_5_4 │ merged_shuffle_0_6_3 │ merged_shuffle_0_7_2 │ └─3f merged_shuffle_0_3_5 merged_shuffle_0_4_4 merged_shuffle_0_5_3 merged_shuffle_0_6_2 merged_shuffle_0_7_1
结论:使用consolidateFiles选项后,
1)不论Mapper多少,产生的文件个数以merged_shuffle_开头,
2)个数为Reducer的个数*并行度(这里的并行度有可能大于系统内核数)
3)产出的结果为乱码,也就是压缩过的
merged_shuffle_m_r_n
m: shuffleId
r: reducerId
n: fileId
3. 流程
3.1 ShuffleMapTask的runTask方法
override def runTask(context: TaskContext): MapStatus = { // Deserialize the RDD using the broadcast variable. val ser = SparkEnv.get.closureSerializer.newInstance() val (rdd, dep) = ser.deserialize[(RDD[_], ShuffleDependency[_, _, _])]( ByteBuffer.wrap(taskBinary.value), Thread.currentThread.getContextClassLoader) metrics = Some(context.taskMetrics) var writer: ShuffleWriter[Any, Any] = null try { val manager = SparkEnv.get.shuffleManager ///根据mapper的一个PartionId获取一个writer对象,此处是HashShuffleWriter writer = manager.getWriter[Any, Any](dep.shuffleHandle, partitionId, context) ///将partition数据转换成iteratable对象,传给writer.write方法 writer.write(rdd.iterator(partition, context).asInstanceOf[Iterator[_ <: Product2[Any, Any]]]) return writer.stop(success = true).get } catch { case e: Exception => try { if (writer != null) { writer.stop(success = false) } } catch { case e: Exception => log.debug("Could not stop writer", e) } throw e } }
3.2 调用HashShuffleWriter的write方法
override def write(records: Iterator[_ <: Product2[K, V]]): Unit = { val iter = if (dep.aggregator.isDefined) { if (dep.mapSideCombine) { ///map端combine dep.aggregator.get.combineValuesByKey(records, context) } else { records } } else { require(!dep.mapSideCombine, "Map-side combine without Aggregator specified!") records } for (elem <- iter) { //根据Reducer的分区算法获取当前遍历的elem应该属于哪个分区 val bucketId = dep.partitioner.getPartition(elem._1) ///根据bucketId得到要执行写操作的writer ///一个partition里面的数据elem不同会写向不同的reducer writer ///因为多个mapper同时操作,那么如何保证它们写入是不冲突呢? shuffle.writers(bucketId).write(elem) } }
3.3 执行shuffle.writers(bucketId).write(elem)方法
3.3.1 shuffle是如下代码创建的
private val shuffle = shuffleBlockManager.forMapTask(dep.shuffleId, mapId, numOutputSplits, ser, writeMetrics)
shuffleBlockManager是FileShuffleBlockManager类型的对象,在forMapTask这个方法中,就使用了consolidateFiles选项,默认为false,需要将它设置为true
private val consolidateShuffleFiles = conf.getBoolean("spark.shuffle.consolidateFiles", false)
3.3.2 FileShuffleBlockManager.forMapTask方法的代码
//shuffle变量的类型是ShuffleWriterGroup //shuffleId //mapId:mapper partition的index //numBuckets:reducer的partition总数 //serializer def forMapTask(shuffleId: Int, mapId: Int, numBuckets: Int, serializer: Serializer, writeMetrics: ShuffleWriteMetrics) = { new ShuffleWriterGroup { shuffleStates.putIfAbsent(shuffleId, new ShuffleState(numBuckets)) ///suffleState仅仅在consolidateShuffleFiles为true时使用 /// private val shuffleState = shuffleStates(shuffleId) private var fileGroup: ShuffleFileGroup = null //writers的元素个数都为Reduce个数个 val writers: Array[BlockObjectWriter] = if (consolidateShuffleFiles) { ///使用了consolidateShuffleFiles,表示每个mapper都是复用R个文件? ///首先获取一个未使用的FileGroup fileGroup = getUnusedFileGroup() Array.tabulate[BlockObjectWriter](numBuckets) { bucketId => ///blockId,类型为ShuffleBlockId,bucketId就是reduceId val blockId = ShuffleBlockId(shuffleId, mapId, bucketId) ///获取一个BlockObjectWriter blockManager.getDiskWriter(blockId, fileGroup(bucketId), serializer, bufferSize, writeMetrics) } } else { //没用shuffleState变量 Array.tabulate[BlockObjectWriter](numBuckets) { bucketId => val blockId = ShuffleBlockId(shuffleId, mapId, bucketId) val blockFile = blockManager.diskBlockManager.getFile(blockId) // Because of previous failures, the shuffle file may already exist on this machine. // If so, remove it. if (blockFile.exists) { if (blockFile.delete()) { logInfo(s"Removed existing shuffle file $blockFile") } else { logWarning(s"Failed to remove existing shuffle file $blockFile") } } blockManager.getDiskWriter(blockId, blockFile, serializer, bufferSize, writeMetrics) } }
3.3.3 writers的初始化是在if(consolidateShuffleFiles)代码中,首先调用getUnusedFileGroup获取一个ShuffleFileGroup对象,然后再执行如下方法,填充长度为numBuckets的数组(数组类型为BlockObjectWriter)。
val writers: Array[BlockObjectWriter] = if (consolidateShuffleFiles) { ///获取未使用的FileGroup,如果已经在队列里,则直接返回,否则新创建一个 fileGroup = getUnusedFileGroup() Array.tabulate[BlockObjectWriter](numBuckets) { bucketId => val blockId = ShuffleBlockId(shuffleId, mapId, bucketId) ///fileGroup(bucketId)返回的是一个文件,应该是往这个bucketId中写入数据的文件 blockManager.getDiskWriter(blockId, fileGroup(bucketId), serializer, bufferSize, writeMetrics) }
3.3.4getUnusedFileGroup方法
//这里面ShuffleFileGroup有重用的机制在里面,当一个ShuffleFileGroup被回收后,它可以被其它的map task使用,因此, //多个map task有可能往同一个ShuffleFileGroup中写入数据 //正因为如此,ShuffleFileGroup中的每个文件是可能分段的,每个map task写入一段(称为FileSegment) //虽然ShuffleFileGroup中的每个File都可能有多个FileSegment,但是它们都属于一个Reducer要处理的数据,因此Reducer只要去这整个文件即可,而无需考虑文件内容已经分段,而这正是hash based shuffle write的好处,否则 //如果考虑排序的话,那么需要对所有的segment进行merge 排序 // private def getUnusedFileGroup(): ShuffleFileGroup = { //shuffleState.unusedFileGroups是ConcurrentLinkedQueue,poll操作是从队列头取走一个 ///这里是一个优化,unusedFileGroups是一个队列,有取就有放,recycleFileGroup方法在回收一个FileGroup后就放入这个unusedFileGroups队列中,这样的目的是 ///尽可能的复用已经创建的ShuffleFileGroup,但是也引入了不同的map task往同一个ShuffleFileGroup中写入文件 ///复用也就意味着每个Mapper Task执行时,使用的ShuffleFileGroup的是一样的(不会因为mapper partition的不同而导致FileGroup不同) val fileGroup = shuffleState.unusedFileGroups.poll() //如果fileGroup不为空,则复用;否则新建一个 if (fileGroup != null) fileGroup else newFileGroup() } ///新创建一个FileGroup private def newFileGroup(): ShuffleFileGroup = { //由于并行度,而导致这段代码同时运行,因此fileId会有多个,比如上面的local[3]产生了3个fileId //多个Map Task会共享这个ShuffleStage对象 val fileId = shuffleState.nextFileId.getAndIncrement() //files是长度为numBuckets的File数组,因此,一个ShuffleFileGroup有R个File对象 //map task同时运行会产生独立的fileId,可以把fileId想象成避免多线程同时操作同一个文件而引入的一个避免互斥的解决方法 val files = Array.tabulate[File](numBuckets) { bucketId => //文件名定义:一共有R个 val filename = physicalFileName(shuffleId, bucketId, fileId) ///获取文件 blockManager.diskBlockManager.getFile(filename) } //构造ShuffleFileGroup对象,包含了R个文件 //构造ShuffleFileGroup是的入参是fileId以及files,这个files中每个File都有fileId作为其文件名的一部分 val fileGroup = new ShuffleFileGroup(shuffleId, fileId, files) shuffleState.allFileGroups.add(fileGroup) fileGroup }
phyisicalFileName:
private def physicalFileName(shuffleId: Int, bucketId: Int, fileId: Int) = { "merged_shuffle_%d_%d_%d".format(shuffleId, bucketId, fileId) }
可见此时的shuffle结果文件名,有shuffleId,bucketId和fileId,这样的文件一共多少个?
3.3.5构造好了ShuffleFileGroup对象,执行如下的代码逻辑:
Array.tabulate[BlockObjectWriter](numBuckets) { bucketId => val blockId = ShuffleBlockId(shuffleId, mapId, bucketId) //fileGroup是个ShuffleFileGroup对象,fileGroup(bucketId)是什么含义? //返回DiskBlockObjectWriter blockManager.getDiskWriter(blockId, fileGroup(bucketId), serializer, bufferSize, writeMetrics) }
3.3.6 fileGroup(bucketId)
fileGroup对象是一个有shuffleId,fileId和files作为入参构造的,其中files是个长度为R的File数组,每个File都有fileId作为文件名的一部分,而fileGroup(bucketId)使用了Scala的apply语法,这个语句会调用ShuffleFileGroup的apply方法,apply方法定义如下:
def apply(bucketId: Int) = files(bucketId)
可见它是去files数组中的bucketId对应的File
3.3.7
执行语句
blockManager.getDiskWriter(blockId, fileGroup(bucketId), serializer, bufferSize, writeMetrics)
将返回DiskBlockObjectWriter,它里面挂了一个唯一的文件(注意:这个文件有可能已经有数据了)
3.3.8 DiskBlockObjectWriter的write方法
override def write(value: Any) { if (!initialized) { open() } objOut.writeObject(value) //调用SerializationStream,写入数据 if (writesSinceMetricsUpdate == 32) { //每调用write32次,则调用upateBytesWritten更新一下写入数据的字节数 writesSinceMetricsUpdate = 0 updateBytesWritten() } else { writesSinceMetricsUpdate += 1 } }
3.3.9在DiskBlockObjectWriter的类说明中说明了这个类有可能是通过追加的方式写入的,
/** * Cursors used to represent positions in the file. * * xxxxxxxx|--------|--- | * ^ ^ ^ * | | finalPosition * | reportedPosition * initialPosition * * initialPosition: Offset in the file where we start writing. Immutable. * reportedPosition: Position at the time of the last update to the write metrics. * finalPosition: Offset where we stopped writing. Set on closeAndCommit() then never changed. * -----: Current writes to the underlying file. * xxxxx: Existing contents of the file. */
相关推荐
1、文件内容:ibus-table-chinese-erbi-1.4.6-3.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/ibus-table-chinese-erbi-1.4.6-3.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊
选择Java后台技术和MySQL数据库,在前台界面为提升用户体验,使用Jquery、Ajax、CSS等技术进行布局。 系统包括两类用户:学生、管理员。 学生用户只要实现了前台信息的查看,打开首页,查看网站介绍、自习室信息、在线留言、轮播图信息公告等,通过点击首页的菜单跳转到对应的功能页面菜单,包括网站首页、自习室信息、注册登录、个人中心、后台登录。 学生用户通过账户账号登录,登录后具有所有的操作权限,如果没有登录,不能在线预约。学生用户退出系统将注销个人的登录信息。 管理员通过后台的登录页面,选择管理员权限后进行登录,管理员的权限包括轮播公告管理、老师学生信息管理和信息审核管理,管理员管理后点击退出,注销登录信息。 管理员用户具有在线交流的管理,自习室信息管理、自习室预约管理。 在线交流是对前台用户留言内容进行管理,删除留言信息,查看留言信息。
面向基层就业个性化大学生服务平台(源码+数据库+论文+ppt)java开发springboot框架javaweb,可做计算机毕业设计或课程设计 【功能需求】 面向基层就业个性化大学生服务平台(源码+数据库+论文+ppt)java开发springboot框架javaweb,可做计算机毕业设计或课程设计 面向基层就业个性化大学生服务平台中的管理员角色主要负责了如下功能操作。 (1)职业分类管理功能需求:对职业进行划分分类管理等。 (2)用户管理功能需求:对用户信息进行维护管理等。 (3)职业信息管理功能需求:对职业信息进行发布等。 (4)问卷信息管理功能需求:可以发布学生的问卷调查操作。 (5)个性化测试管理功能需求:可以发布个性化测试试题。 (6)试题管理功能需求:对测试试题进行增删改查操作。 (7)社区交流管理功能需求:对用户的交流论坛信息进行维护管理。 面向基层就业个性化大学生服务平台中的用户角色主要负责了如下功能操作。 (1)注册登录功能需求:没有账号的用户,可以输入账号,密码,昵称,邮箱等信息进行注册操作,注册后可以输入账号和密码进行登录。 (2)职业信息功能需求:用户可以对职业信息进行查看。 (3)问卷信息功能需求:可以在线进行问卷调查答卷操作。 (4)社区交流功能需求:可以在线进行社区交流。 (5)个性化测试功能需求:可以在线进行个性化测试。 (6)公告资讯功能需求:可以查看浏览系统发布的公告资讯信息。 【环境需要】 1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境:IDEA,Eclipse,Myeclipse都可以。 3.tomcat环境:Tomcat 7.x,8.x,9.x版本均可 4.数据库:MySql 5.7/8.0等版本均可; 【购买须知】 本源码项目经过严格的调试,项目已确保无误,可直接用于课程实训或毕业设计提交。里面都有配套的运行环境软件,讲解视频,部署视频教程,一应俱全,可以自己按照教程导入运行。附有论文参考,使学习者能够快速掌握系统设计和实现的核心技术。
三菱Fx3u程序:自动检测包装机电机控制模板,PLC脉冲与伺服定位,手自动切换功能,三菱Fx3u程序:自动检测包装机电机控制模板——涵盖伺服定位与手自动切换功能,三菱Fx3u程序,自动检测包装机。 该程序六个电机,plc本体脉冲控制3个轴,3个1pg控制。 程序内包括伺服定位,手自动切,功能快的使用,可作为模板程序,很适合新手。 ,三菱Fx3u程序; 自动检测包装机; 六个电机; PLC脉冲控制; 伺服定位; 手自动切换; 功能快捷键; 模板程序。,三菱Fx3u PLC控制下的自动包装机程序:六电机伺服定位与手自动切换模板程序
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
计及信息间隙决策与多能转换的综合能源系统优化调度模型:实现碳经济最大化与源荷不确定性考量,基于信息间隙决策与多能转换的综合能源系统优化调度模型:源荷不确定性下的高效碳经济调度策略,计及信息间隙决策及多能转的综合能源系统优化调度 本代码构建了含风电、光伏、光热发电系统、燃气轮机、燃气锅炉、电锅炉、储气、储电、储碳、碳捕集装置的综合能源系统优化调度模型,并考虑P2G装置与碳捕集装置联合运行,从而实现碳经济的最大化,最重要的是本文引入了信息间隙决策理论考虑了源荷的不确定性(本代码的重点)与店铺的47代码形成鲜明的对比,注意擦亮眼睛,认准原创,该代码非常适合修改创新,,提供相关的模型资料 ,计及信息间隙决策; 综合能源系统; 优化调度; 多能转换; 碳经济最大化; 风电; 光伏; 燃气轮机; 储气; 储电; 储碳; 碳捕集装置; P2G装置联合运行; 模型资料,综合能源系统优化调度模型:基于信息间隙决策和多能转换的原创方案
IPG QCW激光模块电源驱动电路设计与实现:包含安全回路、紧急放电回路及光纤互锁功能的多版本原理图解析,IPG QCW激光模块电源驱动电路设计与实现:含安全回路、紧急放电及光纤互锁等多重保护功能的原理图解析,IPG QCW激光模块电源驱动电路, 包含安全回路,紧急放电回路,光纤互锁回路等, 元件参数请根据实际设计适当调整,此电路仅供参考,不提供pcb文件 原理图提供PDF和KICAD两个版本。 ,IPG激光模块; QCW激光电源驱动; 安全回路; 紧急放电回路; 光纤互锁回路; 原理图PDF和KICAD版本。,IPG激光模块电源驱动电路图解:含安全与紧急放电回路
基于LSSVM的短期电力负荷预测模型及其性能评估:结果揭露精确度与误差分析,LSSVM在短期电力负荷预测中的结果分析:基于均方根误差、平均绝对误差及平均相对百分误差的评估。,LSSVM最小二乘支持向量机做短期电力负荷预测。 结果分析 均方根误差(RMSE):0.79172 平均绝对误差(MAE):0.4871 平均相对百分误差(MAPE):13.079% ,LSSVM(最小二乘支持向量机);短期电力负荷预测;均方根误差(RMSE);平均绝对误差(MAE);平均相对百分误差(MAPE),LSSVM在电力负荷短期预测中的应用及性能分析
1、文件内容:libmtp-examples-1.1.14-1.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/libmtp-examples-1.1.14-1.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊
资源内项目源码是均来自个人的课程设计、毕业设计或者具体项目,代码都测试ok,都是运行成功后才上传资源,答辩评审绝对信服的,拿来就能用。放心下载使用!源码、说明、论文、数据集一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 4、如有侵权请私信博主,感谢支持
2023-04-06-项目笔记-第四百一十六阶段-课前小分享_小分享1.坚持提交gitee 小分享2.作业中提交代码 小分享3.写代码注意代码风格 4.3.1变量的使用 4.4变量的作用域与生命周期 4.4.1局部变量的作用域 4.4.2全局变量的作用域 4.4.2.1全局变量的作用域_1 4.4.2.414局变量的作用域_414- 2025-02-21
MINIST数据集和春风机器学习框架
1、文件内容:ibus-table-chinese-wu-1.4.6-3.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/ibus-table-chinese-wu-1.4.6-3.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊
宿舍管理系统(源码+数据库+论文+ppt)java开发springboot框架javaweb,可做计算机毕业设计或课程设计 【功能需求】 系统拥有管理员和学生两个角色,主要具备系统首页、个人中心、学生管理、宿舍信息管理、宿舍分配管理、水电费管理、进入宿舍管理、出入宿舍管理、维修信息管理、卫生信息管理、考勤信息管理、留言板、交流论坛、系统管理等功能模块。 【环境需要】 1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境:IDEA,Eclipse,Myeclipse都可以。 3.tomcat环境:Tomcat 7.x,8.x,9.x版本均可 4.数据库:MySql 5.7/8.0等版本均可; 【购买须知】 本源码项目经过严格的调试,项目已确保无误,可直接用于课程实训或毕业设计提交。里面都有配套的运行环境软件,讲解视频,部署视频教程,一应俱全,可以自己按照教程导入运行。附有论文参考,使学习者能够快速掌握系统设计和实现的核心技术。
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
人凤飞飞凤飞飞是粉色丰富
2024蓝桥杯嵌入式学习资料
image_download_1740129191509.jpg
基于Multisim仿真的带优先病房呼叫系统设计(仿真图) 设计一个病房呼叫系统。 功能 (1)当有病人紧急呼叫时,产生声,光提示,并显示病人的编号; (2)根据病人的病情设计优先级别,当有多人呼叫时,病情严重者优先; (3)医护人员处理完当前最高级别的呼叫后,系统按优先级别显示其他呼叫病人的病号。
基于STM32F103的3.6kW全桥逆变器资料:并网充电放电、智能切换与全方位保护方案,基于STM32F103的3.6kW全桥逆变器资料:并网充电放电、智能控制与全方位保护方案,逆变器光伏逆变器,3.6kw储能逆变器全套资料 STM32储能逆变器 BOOST 全桥 基于STM32F103设计,具有并网充电、放电;并网离网自动切;485通讯,在线升级;风扇智能控制,提供过流、过压、短路、过温等全方位保护。 基于arm的方案区别于dsp。 有PCB、原理图及代码ad文件。 ,逆变器; 储能逆变器; STM32F103; 3.6kw; 485通讯; 全方位保护; 智能控制; 方案区别; PCB文件; 原理图文件; ad文件。,基于STM32F103的3.6kw储能逆变器:全方位保护与智能控制