首先非常感谢大家对软件的关注和支持,从第一个帖子开始,就给了我很多鼓励,今天周末有时间,想把之前在帖子中看到的问题和建议整理下,认真的给一个自己比较满意的答复。
这里是长文警告
这个程序有什么意义?
无论是中小学还是高校,已经有很多人和公司在做或者已经完成相关的排课功能了。就我所知的高校来说,一般采购的教务系统都包含排课的功能,这部分功能已经很“成熟”了。
所以这个项目最初不过是用来做为本科学生的一个竞赛项目开始的,使用python开发,从知网搞了一些相关资料,便开始了草台班子的开发,这就是项目最初的意义。
期间和教务的老师聊过一次,得知系统排一次课需要大约一天左右的时间,并且还有很多吐槽,有一些吐槽是关于系统的,有一些是关于课程计划本身的,遂感觉这方面还有挺多工作可以做的,学生的项目虽然已经结束了,但是相关的工作我自己并没有停下来。
试试看自己能不能把这个功能实现的更好,大概就是这个阶段的意义。
于是我把之前的python代码又重新用c++完成,重新规定了数据结构,采用的算法,这是一个不断演进的过程,从时间的顺序上来说,依次用了python->c+±>cpython->python的各种类似numpy的计算库->c++ cpu并行计算->试试OpenMP?->既然并行了,就用cuda和c+±>python用taichi库也可以写cuda->还是回到c++使用cuda,大致经历了这样的技术路线,其中还夹杂着不同数据结构和算法的取舍对程序执行速度和资源的影响,都要写一些小的demo来评估哪种技术路线更好。
例如c++中的map就有几种,日常使用问题不大,如果精细一些,使用 unordered_map速度又会快很多,其实还有更快的,我记得当时找到了一个网站,对各种字典类型的速度做了统计,让我大开眼界,这个世界上总有各种人在把事情做到极致。
后来我发现,如果我把整体的思路换一下,对于这个数据不用字典,而换做vector来做,速度直接起飞,之前对map的探索都是“无用功”。当然,为了适应vector的结构,对代码的逻辑甚至都要大改,对内存的管理和规划要更加贴近设备。逐步的将自己的设计思路从便于人脑直观理解,到让设备更快速的执行。
这样的思考和探索在程序的整个编写过程中几乎无处不在,让我也浅尝辄止的体会一把硬件工程师的感觉,一点点的扣内存和想算法,解决问题的快乐大概就是这个阶段的意义。
从程序能够在cpu上多线程执行后,我就开始准备把它搬到cuda上,排课这种高密度计算的程序,天生就应该使用并行计算。由于专业的原因,之前做过一些计算化学方面的工作,对于gpu在提升计算速度方面的作用印象深刻,于是就寻思迁移程序。
如何用好gpu,本身就是一个问题,我这里举一个例子方便理解。
把程序的整个逻辑都搬到gpu上,还是只迁移需要大量计算的部分?
如果整体迁移,cuda中支持的数据结构很少,程序的编写难度几乎是直线上升,例如cuda中没有vector这样的结构,动态增加数组几乎不可能,原程序中的数据结构全部推翻重来。
如果只使用gpu处理需要大量计算的部分,对代码的修改不多,但是带来的问题是,将需要计算的数据传给gpu,以及返回结果的耗时,每次计算都要将内存中的数据同步到显存,这个耗时是多少,是不是物有所值。
对于具体的程序,上面提到的利弊都要权衡,但是很多结果不是能够简单算出来的,需要代码一行行的写出来,然后测试,对于测试的结果还要分析,目前的速度,是我所选择方案导致的结果,还是我代码写的有问题,方案本身是可以更快的。
这里最该感谢的就是gpt了,说实话,给gpt磕一个都不过分。
然后经过一系列苦逼的思考后,推倒了原来所有的代码,用了一种方法解决了两者无法兼顾的问题,同时还带来了一些意料之外的优点。自认为已经接近这个方法的极致了,因为根据gpt”不严谨“的推算,我的耗时比理论计算还要快…
随着速度的提高,一些工作的意义就逐步浮现出来。
如果我将排课的耗时从一天缩短到一分钟,一天可以获得1440份不同的课表。教务对排课表的耗时其实是不敏感的,一天还是三天,对于教务并没有实质性的区别,反正暑假寒假也不差这几天。优点主要体现在下面几个方面:
一、从海量的课表中可以选择出最符合老师需求的课表,在满足了硬性要求后,尽可能的满足大多数老师对于上课时间的要求,例如课程集中在周几、尽量在上午上课等等软需求。
二、能够压缩上课所需的课时和教室,例如很多学校由于排不开课程等诸多原因,将上午四节课改为五节课;教室的数量不够,需要周六也安排课程。更快的排课速度意味着更有可能探索到合格的解空间。减少所需的课时和教室冗余来完成全校的课程计划。
三、建立全校的教室、寝室、食堂、街道的拓扑图,将每一套课表中学生和老师在课程之间的移动距离计算出来,这个在技术上没有什么难度,然后从1440分课表中筛选出师生总耗时最少、个别班级和老师最长耗时在可接受范围内的解,从而节约师生时间的课表,我觉得这个意义很大。
对于某些人流量高峰拥堵的路段和时间,可以通过合理的选择课表来尽可能调整人流。
四、高校的教务系统,技术含量最多的部分就是排课,其余的部分其实就是数据库的增删改查+前端页面,再加两个后端优化下并发量,应付应付选课。如果排课部分被解决,这个市场的准入门槛就会降低,公司不需要招聘专门的开发去研究排课算法,直接从市场购买,大大节约了人力成本,如果购买我的就更好了,这里给自己打个广告。开发人员至少是java或者c++程序员,一线城市一年的人力成本至少在15~20w,并且不可能只招一年就够了。
既然说到这里了,其实我的程序用户画像就是后端程序员,因为高校的教务几乎是不可能直接使用我的程序进行排课的,必然是使用教务系统。作为个人开发者,没有时间、精力去开发以及维护一个成熟的教务系统,以及完成商务上的一系列操作。我给自己的定位就是做好其中的一个环节,只分得这个环节的利益,集中精力将排课的功能做好。想通了这点,程序的很多功能定位就清晰了,例如不进行图形化界面的开发,使用配置文件进行输入和输出。话又说回来,对于真正的教务人员来说,用excel配置一些csv文件,稍加学习并不是什么难事。至于中小学的排课功能,其实就是顺带做的,程序上并没有做什么额外的改变,属于顺手做了的情况。
五、即便是对于已经成熟的相关公司,在用的程序可能十之八九也是基于cpu开发的,排课期间所需的服务器的成本肯定远远高于一个旗舰显卡的成本,这部分节约的资金也是相当可观,更何况如果给学校提供了我上面所说的节约教室和师生时间的优化服务,可以额外收取一些费用,因为给学校的物业节约的资金是以万计的。
当然,如果真的一分钱也赚不到,把一个事情做到极致,也是很酷的。
其实程序跑通后,我有了一个短时间可以生成大量课表的方法,可以作为变分编码器vae的输入数据,让各种神经网络的结构来学习后生成原始课表。写了一个小的脚本后,发现采用这种方法可以将排课的耗时缩短到二分之一。但是生成的速度太慢了,如果没有针对性的改造的话,完全没有实用价值,但却是水论文讲故事的一个好方法,哈哈哈。
感谢能够看到这里的朋友,这里我分享一句雷军在《小米创业思考》(一本很推荐的书)对于做产品的建议:专注、极致、口碑。