OO的奇妙冒险 多线程入门与魔鬼的优化

目录

  • 总体分析
  • 作业内容分析
  • 作业内容总结
  • 互测的收获
  • 公测互测bug分析与总结
  • 优化分析
  • 不太正经的个人自嗨

总体分析

公测

  • 中测(基础与进阶):

    • 这一单元的作业相比于第一单元,在中测方面可以说变得更加简单了。没有了WF的检测,基本上随便写写就能过中测,更何况中测的难度肉眼可见的降低了
  • 强测(正确性):
    • 强测的正确性其实也不是特别难搞。在这三次作业中,我只在我第三次作业的第一个架构中发现了正确性bug,但更换了正确性有保障的新架构后,就没有特别严重的bug了。和中测同理,在没有WF的情况下,通过强测的正确性也不太困难。
  • 强测(性能):
    • 第一次作业没有性能分,直接跳过
    • 第二次作业我一开始的思路是,ALS比较垃圾所以我要用Look。接下来我写了Look算法的底层,加入了常数优化和转向优化。在周一晚上和同学讨论之后,发现了输出流可以重定向,由此衍生出来自己的Look+纯Look+ALS的三电梯模式。受于时间限制和没有写出SSTF或随机+搜索,性能分很低
    • 第三次作业我快被自己的性能蠢哭了。我首先从第二次的架构继承了一个出来,但是有软件性的死锁bug。换了新架构后,采用非常简单的动态规划+Scan算法,性能分几乎为0。事后想来,主要的bug还是出在Scan身上。用Look肯定会更好一些。

互测:

  • 这一单元的互测总体来说就是两个字:无聊。。
  • 在没有WF并且没有Tmax的环境下,只要好好写作业并做一些基础的测试,应该都没有什么正确性bug。与同学交流后总结出,这次的bug主要还是线程安全问题,也就是硬件问题。当然软件导致死锁的事情也时有发生,不过一般在提交前就解决了。
  • 虽然事后发现并没有正确性bug,但谁能在互测阶段就如此自信呢。在考虑到自己的实际能力比较低与可能出现的强测备份样例后,我这次的互测策略大概是:随便扫几个,重点关照类比较神奇的扫几个,然后开始空刀刷到16刀。在匿名的互测屋中,我既无法确定对方是扫完后没查到bug还是压根儿不会扫,又无法确定我这里扫出来没bug是真没bug还是数据生成器或SPJ有问题。因此,第6次作业我空刀8刀,第七次作业我空刀14刀。也许只有达到16刀的限制我才能安心吧。

作业内容分析

  • 第一次作业不是一般,也不是简单,而是非常简单。有多简单呢?之后的类图或者方法分析我就不讨论第一次作业了。下面直接贴出我第一次作业的全部代码:

    import com.oocourse.TimableOutput;
    import com.oocourse.elevator1.ElevatorInput;
    import com.oocourse.elevator1.PersonRequest; public class Main {
    public static void main(String[] args) throws Exception {
    ElevatorInput elevatorInput = new ElevatorInput(System.in);
    int height = 1;
    PersonRequest task;
    TimableOutput.initStartTimestamp();
    while ((task = elevatorInput.nextPersonRequest()) != null) {
    Thread.sleep(500 * (Math.abs(height - task.getFromFloor())));
    TimableOutput.println("OPEN-" + (height = task.getFromFloor()));
    TimableOutput.println("IN-" + task.getPersonId() + "-" + height);
    Thread.sleep(500);
    TimableOutput.println("CLOSE-" + height);
    Thread.sleep(500 * (Math.abs(height - task.getToFloor())));
    TimableOutput.println("OPEN-" + (height = task.getToFloor()));
    TimableOutput.println("OUT-" + task.getPersonId() + "-" + height);
    Thread.sleep(500);
    TimableOutput.println("CLOSE-" + height);
    }
    }
    }
  • 下面从第二次作业开始分析。

    • 第二次作业正确性也比较简单,维护一个等待队列和内部人员队列,然后直接向两边查找写Look算法即可。事后想来,第二次作业的优化其实很没有必要。理论上说,在有了输出流这个架构之后,完全可以写成Scan算法+随机概率p的转向。因为这样便可以涵盖几乎所有的情形。如果p按照常数从0.0跑到99.9,那么小概率能出现OPT。如果p是取决于当前状态(高度,方向,队列人数,队列人的状态)的话,估计很容易出现OPT。如果构造阶数比较高的马尔科夫模型,那不用多策略都有可能出现OPT。至于NN什么的,随便yy一下就好了。真放在OO课程中是不可能有人直接调model的。
    • 除了这种正常的基于期望的优化,还有另一种也是事后诸葛亮的基于数据点的优化。如果能提前摸到强测数据的针对性,那应该每一个极端情况写一个算法然后多策略,应该效果也不错。
    • 说了这么多,实现起来我就比较菜了。我只实现了Look+轻微的优化,ALS没写对,SSTF没写,随机性更是没有利用起来。不说了,说多了都是泪
  • 然后是第三次作业。

    • 总的来说,第三次作业我真是蠢爆了。我采用的是比较安全比较灵活的架构,但是性能爆垃圾。原因在于,我采用了类似Scan的算法。换句话说,如果底层忙而高层出现了一个请求,那么我的三个电梯都会被吸引上来。我曾经diss的分配实际效果比我高到不知道哪里去了。
    • 我的主要方式是,建立建筑类,输入一个请求就创建一个人,当他的高度达到了他的target并且他处在任一部电梯的外部,那么就销毁他。然后电梯Scan的调度,每到一层先看要不要开,如果要开就把内部人员全部踢出去,这样可以比较方便的实现任意换乘和高并发下的动态进入。然后相对的实现judgeIn方法即完成任务。总体代码量比较小
    • 线程安全方面,硬件(底层,单例类,交互等)主要靠线程安全容器无脑实现。软件(死循环,死锁等等)主要靠架构避免。我电梯为主的硬件方面,不会产生任何轮询相关的问题,无脑Scan虽然性能爆垃圾,但是正确性比较好保证。
    • 性能方面,这次的性能应该使用动态绑定,或者说动态分配的技术。我这次的性能方面,其实是一种静态分配,即任何一个任务,都同时分配给了3部电梯。实际效果其实还不如我曾经diss过的另一种静态分配——只分配给一部电梯。在我与同学讨论后采用的能开门即全部OUT的基础上,实现动态绑定还是不太困难的。但是,由于个人能力原因,我知道周二中午才完成新架构的实现,周二晚上才进行了基础的测试,因此性能爆零。

互测的收获

  • 这一单元互测的收获大概可以直接跳过了叭

公测互测bug分析与总结

  • 如果性能bug不算bug的话,那这次公测互测我没有被找到bug。不过在于同学讨论后,我发现主要的bug集中于软件的隐形死锁。我自己之前也出现过A电梯没有15楼的需求却有着15楼的欲望,欲望得不到满足于是在15层疯狂日门的情况。

优化分析

  • 总体来看,这一单元的正确性没有特别多的问题,主要问题还是出在性能上。
  • 我在优化的时候体会到,优化是没有极限的。不是OPT的算法越优化,就越会发现确定性算法是有局限的。除非超越确定性算法。。。。
    • 我在优化中经常发现,面对各种各样的情况,想出各种各样的算法,最终都会追溯到随机性。我觉得,一个面向未知进行优化的模型,几乎只能依靠经验+概率。概率如何采用?我曾经尝试过完全随机,仅依赖当前状态这两个算法,并且探索过马尔科夫模型的可行性(然而太菜写不出来)。如果不想把决定权交给random,我只能通过主观判断大概率时间进行调度。
    • 当然,这种根据经验获取输出的当然不能无脑推给NN,还是要自己想一些算法的。无脑Scan一时爽,强测出分火葬场。对于一个算法完全0基础的人来说,利用确定性算法进行优化难且不实际。我在与同学讨论后发现,利用随机性的话,是有概率超过dalao写的高级确定性算法的。
    • 不过正如我之前想过的另一个问题:暴搜暴死,随机算法随机死。只要不是确定性的多项式算法,都有原地爆炸的可能。以我现在的视野,能看到的最逼近OPT的算法就是隐马尔科夫模型了。
  • 提到优化,不仅有上面提到了算法级的优化,还有很多常数级的优化。
    • 在经历了DS大作业后,我感觉常数优化一无止境而不稳定,因此从一开始就没有做出过多的常数优化。第二次作业出现了一些小插曲,不过第三次作业确实可以看到,常数优化没人权,不做也罢

自嗨

  • 第一次作业被晾了那么久了,拿出来说说吧

    • 我一开始是按照第七次作业没有超载的模式来构建第一次作业的。写了一部分之后我发现,他给的输入是阻塞式的。考虑到傻瓜调度的特殊性与没有性能分的客观实际,我想拿这次作业来玩一玩。我写出了一个30多行的程序。在与同学讨论并进行简化后,我成功压缩到了24行,轻松地完成了第一次作业。
  • 不得不说,第一次作业还是没啥好说的,直接从2开始。第二次的优化方案和可能的优化方案前文已经提及,这里主要讲一下第二次作业之后的一些感想。
    • 第二次作业我从主观上来说还是做了一些优化。因此,我仔细查看了每一个强测样例丢分的原因。256组完全被评测姬的前摇坑了,14组没写SSTF是自己太蠢,10组很神秘,可能是常数优化不够。与之对应的,是可怕的输出流重定向。在可预见的实现难度下,第三次作业一定会有暴搜党和疯狂多策略,混合多策略党。
    • 因此我直接建议禁止输出流,增加强测样例来体现平均,试图克服运气因素(运气因素的解决方法大概是,让OPT更难写出。毕竟我自己蠢的话是赖不了评测姬的)。然而我从一开始就错误的设计了算法,因此我第三次强测同样很低。
  • 最后是第三次作业
    • 由于对第二次的架构不满,我周日重新设计了整体架构,几乎全都推倒重来。然而,我周日和周一的大部分时间被消耗在了OS的debug上,因此完全没能好好地设计算法。最后我直接采用了Scan算法,可想而知,性能爆零。不过令我惊奇的是,我居然还有一组数据性能100,可能是我比较喜欢这组数据吧。
  • 最后,中测真的不可靠,assert+err.println+简易对拍基本才能确保正确性的基本要求

OO的奇妙冒险2的更多相关文章

  1. OO的奇妙冒险1

    OO的奇妙冒险 ~OOP入门与字符串处理~ 目录 总体分析 作业内容分析 作业内容总结 互测的收获 公测互测bug分析与总结 不太正经的个人自嗨 总体分析 公测 中测(基础与进阶): 其实在我看来,从 ...

  2. OO的奇妙冒险——OOP入门与字符串处理

    OO的奇妙冒险 ~OOP入门与字符串处理~ 总体分析 公测 中测(基础与进阶): 其实在我看来,从完成作业的角度来说,中测的基础与进阶并没有任何区别,都不能挂,都不太难,都对得分没有什么影响.中测的样 ...

  3. GLUT的简洁OO封装

    毕业设计用到了OpenGL,由于不会用MFC和Win32API做窗口程序:自然选用了GLUT.GLUT很好用,就是每次写一堆Init,注册callback,觉得有点恶心,于是对他做了简单的OO封装.记 ...

  4. Atitit 基于sql编程语言的oo面向对象大规模应用解决方案attilax总结

    Atitit 基于sql编程语言的oo面向对象大规模应用解决方案attilax总结 1. Sql语言应该得到更大的范围的应用,1 1.1. 在小型系统项目中,很适合存储过程写业务逻辑2 1.2. 大型 ...

  5. OO中,先有对象还是先有类?

    就是问,在面向对象思想里,先有对象还是先有类,乍一看和先有鸡蛋还是先有鸡是一类问题,其实不然!这个问题,在lz考研复试的时候被面试官问过,一模一样,如今又在一个笔试题里看到了类似的题目,眨一下,有人会 ...

  6. OO方式下,ALV TREE和ALV GRID的不同之处

    作为大部分报表程序的基础,ALV GRID差不多是每个ABAP开发者必须了解和掌握的内容,因此网上也不乏相关资料,而ALV TREE的应用相对较少,中文资料也就比较少见了.实际上,ALV TREE和A ...

  7. 从人类社会的角度看OO(独家视角)

    引言 在OO的工作中,我们一定会涉及到类,抽象类和接口.那么类和抽象类以及接口到底扮演的什么角色? 本文主要是从人类社会的角度阐述类与抽象类以及接口的"社会"关系,从而让我们抛弃书 ...

  8. HDU5288 OO’s Sequence

    Problem Description OO has got a array A of size n ,defined a function f(l,r) represent the number o ...

  9. lua下的简单OO实现

    笔者学习了当前(文末各文献)lua下的各种OO实现方法.略作笔记. 也提出了一些自己的想法.主要还是记录供将来着之参考.   1.概述   首先[2]PIL第二版中给出了OO的基于table的实现方式 ...

随机推荐

  1. C# 弹出确定、取消窗口

    if (MessageBox.Show("确定要退出吗?", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Qu ...

  2. C# 链表去重 List 一维 二维 分别使用 Distinct() GroupBy() 方法

    分别使用List中Distinct(),GroupBy()实现链表的去重. 1.先上效果: 一维链表中分别有元素“aa”,"bb",'aa','aa',"cc" ...

  3. 【SparkStreaming学习之三】 SparkStreaming和kafka整合

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk1.8 scala-2.10.4(依赖jdk1.8) spark ...

  4. 【转载】Sikuli安装及使用——基于图像识别自动化工具

    一.Sikuli能做什么? 用屏幕截图的方式,用截出来的图形元素组合出神奇的程序实现自动化安装.卸载软件,自动化测试(Windows.mac应用测试,Web测试,移动端测试) 二.安装Sikuli 预 ...

  5. Python 递归计算分数数列

    C语言的课后习题 求数列:2/1,3/2,5/3,8/5,13/8,21/13,...前50项的和 数列规律: 第二项的分母是[前一项分子] 第二项的分子是[前一项分子与分母的和] from frac ...

  6. ARMLCD屏调试2--ili9325驱动编写

    2011-06-24 21:57:09 一,读id--完成 二,自己写了驱动--完成 三,调试LCD屏驱动--完成 一         读id,不过过程还有点曲折. 因为之前写命令写数据的时序是根据i ...

  7. textfield reload issue and other things reload problem.===================================

    https://github.com/flutter/flutter/issues/18828 https://blog.csdn.net/u011272795/article/details/830 ...

  8. Django Form表单组件

    Form介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否 ...

  9. 课后作业机票,赌骰子游戏,switch的使用实例

    一,课后第三题机票 package com.bd22; import java.util.Scanner; public class AirTicket { public static void ma ...

  10. python笔记---@classmethod @staticmethod

    python定义类方法的三种方式: 1.常规方式--需要通过self参数隐式的传递当前类对象的实例 2.@classmethod修饰方式--@classmethod修饰的方法class_foo()需要 ...