关于计算机科学:个人GitHub

最近从码云转战GitHub,所有新的开始 为了记录成长过程,创立了一个常识分享我的项目,将学习或者工作上学习到的记录下来,也是作为本人的别样形式的笔记本吧,同时也心愿能帮忙到其他人最初,如果该我的项目帮到你的话,也欢送点个星星 地址:https://github.com/qian-lou/c...

November 14, 2021 · 1 min · jiezi

关于计算机科学:学技术没有什么捷径

这篇文章次要来自我 2019 年末写的总结,在此基础上稍作批改。次要是回顾一下本人的成长历程。当然,如果对其他人有帮忙,那就更好了。 1.有没有什么捷径?16 年大二下,我无意间看到 Fenng 的公众号小道消息在推一个小密圈(当初叫常识星球)的利用,过后看收费棘手就进了。说实话,刚开始进去的时候,老是在想有没有捷径,胜利的秘诀之类的,翻遍了精华区也没有找到!在圈子里呆了一段时间,发现如同大多人都是一步步走,并没有谁什么奇技淫巧,平步青云。 2.学什么呢?17年上半年,各个公众号,各个新闻,就连校园里,一天到晚都在讲云计算,大数据,机器学习,人工智能。我要不要去学下? 抵制不了引诱,本人也不思考,看着也挺乏味,那就去试试呗。看了一段时间如同不太懂,数学根底不够,那些公式都不会推导。你要是我读英文文档,调 API,跑起来不难,让我本人了解透彻改良,不太行。简略来说,就只能把这些货色当做黑盒来用。 本人之前学了点Java,而后就在纠结本人该学什么了,Java 还是机器学习?于是就有了上面的问答。 看了冯大的答复,本人又不打算考研,就老老实实温习,先筹备面试。冯大说的打基础,但过后还是没闹分明根底要学到什么水平,一方面是懒,一方面是认知无限。 3.先搬会砖?18年下半年,入职了当初的公司,面向 API 编程对我而言是不难的,但时不时就会陷入困惑,脑袋里一团浆糊,到底计算机外面产生了什么?举个例子,比方多线程并发,到底线程和过程共享哪些数据?如何平安地拜访这些共享数据? 疑难越多,焦虑越多。为此我先后买了极客工夫 26 门课程,迄今为止大概学了其中的一半多一点,但的确学到了很多。可这些课程大多是偏差于实战的,计算机系统原理讲的较少。所以还是没有彻底解决我的疑难, 或者说本人还没有能力将这些常识串联起来。 4.嗯,从头再来我大学业余是软件工程,可工作了才发现就只会各种编程语言的拼写。当然考试对于计算机的课程分数都还挺不错,俨然一副自我感觉良好的模样。我不晓得以本人过后的程度如何考的 90 多分,可能是老师出的题太简略些了,都给咱们划好了重点了吧。 我想这样不行啊,于是就去钻研 Java 的并发编程库,于是我看到了 Java 调用 C, C 调用汇编指令。这时才下定决心把冯大举荐的计算机自学门路拿过去认真看看!依据冯大的举荐门路和陈皓的左耳听风练级攻略学习, 并在豆瓣上建设了一个豆列来记录本人要看的书。 对于一般大学的计算机教育,值得思考的中央很多,我懂的不多,权当交换。学校的课程是否正当(课程先后顺序正当吗?学那么多编程语言有必要吗?微软C#那一套还有必要吗?教材真的要本人搞一套吗?)。老师是否与时俱进,还是在原地踏步呢?当然,更重要的是,本人又做了什么呢?环境和别人都是咱们不好扭转的,扭转本人是最容易的——齐全能够自学啊。 5.总结学技术没有捷径,不过认真想想,干什么有捷径呢? 这几年还是有点提高的。 1.去除了一些贪念。没有什么文治秘籍,有的只是前辈们的避坑教训,让你少走弯路。然而一开始老想着走捷径,行不通了才想着听他人的,起因可能一个是懒,一个是无知。看到什么火学什么,其实永远在绕圈子,到达不了起点。很多花枝招展的新技术,大多是底层技术的形象封装,排列组合的形式有千千万万种,如果你流于外表挨个学,那不得累死.. 2.读书多了一点。看了一些书,听了一些失去专栏,去除了本身的一些愚昧与无知。读书多了当前,有一特大的益处,一点儿也不焦虑了,每天看一点就是了,感兴趣的就多看一点。当然也可能只是我认为我晓得了很多货色,其实我并不知道。 感激每一位帮忙我提高的人:Fenng,吴军, 左耳朵耗子,cazsay,MacTalk, stormzhang....

May 22, 2021 · 1 min · jiezi

关于计算机组成原理:计算机组成原理笔记数制Number-Systems

十进制零碎十进制零碎即The Decimal System 在日常生活中,咱们每天都在应用逢十进一的数位(0、1、2、3、4、5、6、7、8、9)来示意数字,这种数制叫做十进制。考查数字83的意义,能够示意成:83 = (8 × 10) + 3即八个10再加上一个3;考查数字4728的意义,能够示意成:4728 = (4 × 1000) + (7 × 100) + (2 × 10) + 8即四个1000加上七个100再加上两个10再加上一个8。 从上得悉,咱们能够说,十进制的基数(base/radix)为10。也即,十进制数是由每个数位的数字乘以10的n次幂,n与数位的地位相干。例如:83 = (8 × 101) + (3 × 100)83是由两个数位形成,最右边的数位为最高(无效)数位,这里是8;最左边的数位是最低(无效)数位,这里是3。最低数位的地位所对应的10的幂为0,从右往左顺次加一。即,数位3为最低数位,故其10的幂为0,示意为3×100;往左挪动一位,数位为8,其10的幂为1,示意为8×101,将所有数位相加失去的和即该十进制数,也即,8×101+ 3×100= 83应用同样的办法拆解数字4728,示意如下:4728 = (4 × 103) + (7 × 102) + (2 × 101) + (8 × 02) 咱们应用同样的办法示意小数局部,只不过小数局部数位的10的幂为正数。其最大的数位的10的幂为-1,从左向右其数位的10的幂顺次减1。例如:0.256 = (2 × 10-1) + (5 × 10-2) + (6 × 10-3) 在一个既有整数局部又有小数局部的十进制数中,其数位的10的幂也既有负数又有正数:442.256 = (4 × 102) + (4 × 101) + (2 × 100) + (2 × 10-1) + (5 × 10-2) + (6 × 10-3) ...

April 9, 2021 · 2 min · jiezi

关于计算机科学:2020-年-ACM-杰出科学家榜单揭晓26-位华人学者上榜

2020 年 ACM 卓越科学家名单曾经出炉,表彰了 64 位在计算机领域的卓越贡献者。 这次入选的卓越科学家中共有 26 位华人学者,其中 1 位取得工程卓越贡献奖,25 位取得迷信卓越贡献奖。 入选 ACM 卓越科学家的规范包含业余教训以及在计算机领域的重大成就,候选人必须在计算机领域具备至多 15 年的业余教训,并且在计算、计算机科学或信息技术畛域获得了显著成绩。 这 64 位卓越科学家别离来自澳大利亚、加拿大、中国、印度、卡塔尔、新加坡、西班牙、瑞典、英国、美国的定价大学和钻研机构,他们在宽泛的技术畛域做出了奉献,包含数据迷信、人工智能、计算机工程、网络安全等等。 以下为入选 2020 年 ACM 卓越科学家华人学者名单: 1.何奇,现任 LinkedIn 高级工程总监; 2.叶杰平,美国密歇根大学一生传授、IEEE Fellow,现任贝壳技术副总裁、首席科学家; 3.崔鹏,清华大学长聘副教授; 4.白帆,IEEE Fellow,现任通用汽车钻研与开发高级研究员; 5.操龙兵,中科院模式识别与智能零碎博士、中科院海内评审专家、中国科学技术大学/上海交通大学客座教授、澳大利亚悉尼科技大学工程与信息技术学院传授、悉尼科技大学高级剖析研究所的创所所长; 6.陈浩,加州大学戴维斯分校计算机科学系一生传授; 7.陈名华,香港城市大学数据迷信学院传授,香港城市大学香港数据迷信研究所助理所长; 8.高剑峰,微软研究院 AI 深度学习小组的合作伙伴钻研经理,IEEE院士; 9.郭嵩,香港理工大学计算系传授、IEEE ComSoc卓越讲师; 10.何丙胜,新加坡国立大学计算机学院计算机科学系副教授; 11.姬水旺,Texas A&M University 计算机科学与工程系副教授; 12.李蕴瑶,IBM Almaden 钻研核心高级钻研经理和首席研究员; 13.刘燕,南加州大学声誉副教授,机器学习核心主任; 14.马晓松,卡塔尔计算机研究所(QCRI)首席科学家; 15.田媛媛,IBM Almaden钻研核心研究员,本科就读于北京大学计算机专业; 16.童行行,伊利诺伊大学香槟分校计算机科学系副教授; 17.王昱,天普大学计算机与信息科学系传授,本科毕业于清华大学; 18.杨天若,圣弗朗西斯泽维尔大学教授,本科就读于清华大学,取得计算机和利用物理双学位; 19.张洪宇,现任澳大利亚纽卡斯尔大学副教授; 20.张霖涛,翼方健数首席科学家,本科毕业于北京大学; 21.Xue (Steve) Liu,麦吉尔大学计算机科学学院传授、三星AI核心(蒙特利尔)研发副总裁、IEEE Fellow; 22.Albert Mo Kim Cheng,休斯敦大学计算机系实时零碎实验室传授23.杨凤如,香港中文大学计算机科学与工程系传授; ...

December 18, 2020 · 1 min · jiezi

2019未来科学大奖公布邵峰王贻芳陆锦标王小云分获三个奖项

9月7日下午,第四届未来科学大奖获奖名单正式公布。邵峰获生命科学奖,王贻芳、陆锦标获物质科学奖,王小云获数学与计算机科学奖。 为奖励王小云教授在密码学中的开创性贡献,特此为其颁发了本届数学与计算机科学奖。她的创新性密码分析方法揭示了被广泛使用的密码哈希函数的弱点,促成了新一代密码哈希函数标准。 未来科学大奖成立于2016年,是中国大陆第一个由科学家、企业家群体共同发起的民间科学奖项。未来科学大奖关注原创性的基础科学研究,奖励在大中华区取得杰出成果的科学家(不限国籍)。奖项以定向邀约方式提名,并由优秀科学家组成科学家委员会专业评审,秉持公正、公平、公信的原则,保持评奖的独立性。 未来科学大奖,目前设置“生命科学”“物质科学”和“数学与计算机科学”三个奖项。生命科学奖涵盖所有与大生命学科相关的基础科学领域,包含医学、偏生物的基础化学;物质科学奖涵盖所有与物质科学相关的基础科学,如物理、化学;数学与计算机科学奖涵盖数学与计算机学科相关的基础和应用研究。每个奖项获奖人数不超过5位,每一奖项由四位捐赠人共同捐赠,每人出资25万美金,单项奖金100万美金。 新闻来源:未来科学大奖官网

September 7, 2019 · 1 min · jiezi

堆栈的基本了解

一、概述1.1大致目的对计算机操作系统中的堆和栈的作用有一个初步的了解。(本篇)对数据结构中的堆和栈有一个初步了解。(本篇)理解java虚拟机中堆和栈等其他内存区域的作用和运行时的基本原理。(第三篇)理解java中变量、对象、方法与堆、栈的关系。(第三篇)1.2堆栈注意: ①我们有时候会遇到“堆栈”这种称呼,根据语义“堆栈”这种称呼无非等价以下两种说法: 表示“堆”和“栈”的合称。表示栈。②操作系统的堆和栈是指对内存进行操作和管理的一些方式这和数据结构中的堆和栈是有区别的。 二、计算操作系统中的栈(stack)在计算机系统中,栈也可以称之为栈内存是一个具有动态内存区域,存储函数内部(包括main函数)的局部变量和方法调用和函数参数值。我们需要知道: 栈的基本性质栈帧的概念栈的存储形式及数据的存储和函数的调用。2.1栈的基本性质①内存管理:栈由编译器自动分配释放。②栈中的内容存放栈存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。满足:“先进后出”的原则存取,也就是位于栈内的元素,必须等到其上面(对应的地址为较低的地址)的数据或函数执行完成后,弹出后才可以进行下面的元素的操作。③栈的结构:栈的一端是固定的,另一端是浮动的。固定的一端是较高的地址,我们称栈顶。浮动的一端是较低的地址(最低到0)随着元素或方法的加入栈顶指针会逐步地往下移动。所有的数据存入或取出,只能在浮动的一端(称栈顶)进行。(栈的生长方向是向下的,是向着内存地址减小的方向增长)④栈的速度:栈是由系统自动分配的,一般速度较快(栈的速度高于堆的速度)⑤申请大小的限制:栈是向低地址扩展的,是一块连续的内存的区域。是栈顶的地址和栈的最大容量是系统预先规定好的,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数 ) ,如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。⑥单片机中的栈:单片机应用中,栈是个特殊存储区,栈属于RAM空间的一部分,栈用于函数调用、中断切换时保存和恢复现场数据。栈中定义了一些操作,两个最重要的是PUSH和POP。 PUSH(入栈)操作:堆栈指针(SP)加1,然后在堆栈的顶部加入一 个元素。POP(出栈)操作相反,出栈则先将SP所指示的内部ram单元中内容送入直接地址寻址的单元中(目的位置),然后再将堆栈指针(SP)减1。这两种操作实现了数据项的插入和删除。 2.2栈帧的概念函数的每一次调用,均会在调用栈(call stack)上维护一个独立的栈帧(stack frame).每个独立的栈帧一般包括:①函数的返回地址和参数。②临时变量: 包括函数的非静态局部变量以及编译器自动生成的其他临时变量。③函数调用的上下文。栈是从高地址向低地址延伸,一个函数的栈帧用ebp和esp这两个寄存器来划定范围.ebp 指向当前的栈帧的底部,esp 始终指向栈帧的顶部;ebp 寄存器又被称为帧指针(Frame Pointer);esp 寄存器又被称为栈指针(Stack Pointer); 2.3栈和函数的调用关系下面以函数P内部调用函数Q为例: ①在函数P调用函数Q的过程,Q在执行时,P以及所有在向上追溯到P的调用链中的过程,都是被暂时挂起的。②当Q运行时,它只需要为局部变量分配新的储存空间,或者设置另一个过程的调用。③Q返回时,任何它所分配的局部存储空间都可以被释放。当P调用Q时控制和数据信息会添加到栈尾,当P返回时,这些信息会被释放掉。对于调用中栈帧的过程:①当前正在执行的栈帧总是在栈顶,当过程P调用过程Q时,会把返回地址压入栈中,指明当Q返回时,要从P程序的哪个位置继续执行。并且这个返回地址当作P的栈帧的一部分。因为它存放的是与P相关的状态。②Q的代码会推展当前栈的边界,并分配它的栈帧所需的空间。这个空间中,Q可以保存寄存器的值,分配局部变量空间,为它调用的过程分配参数注意:并不是所有函数都学要栈帧的,比如不调用任何子函数的函数。 三、计算操作系统中的堆(heap)3.1堆的基本了解①堆的内存管理:堆是程序中一块预留的内存空间,可由程序自由使用,堆被程序申请使用的内存在被主动释放前一直有效。一般由程序员分配释放, 若程序员不释放,对于堆来讲,释放工作由程序员手动管理,不及时回收容易产生内存泄露。 程序结束时可能由操作系统回收。②C中对空间的申请:C语言程序中通过头文件为“malloc.h”的库函数调用获得堆空间,关键字“malloc”以字节的方式动态申请堆空间,关键字“free”将堆空间归还给系统。③堆的速度:有种说法是“栈是存放在一级缓存中的,而堆则是存放在二级缓存中的,堆的生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。”所以调用这些对象的速度要相对来得低一些,故堆的速度慢于栈的速度。④系统对堆空间的管理方式:我们了解下空闲链表法这种管理方式::首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。下部分描述参见:程序中的三国天下:栈、堆、静态存储区:分析:假设每个节点下的内存都为 12byte、100byte、50byte....当申请内存时,系统遍历空闲链表节点,查看所需内存大小与哪一个节点下内存大小最接近到此节点下查找可用单元,查找到之后返回对应单元地址在空闲链表管理法中,存在查找所需内存大小与哪一节点最接近的操作,这将导致 malloc 实际分配的内存可能会比请求的多。但我们不能依赖这种行为,因为在不同的系统中,对堆空间的管理方式可能是不同的。 3.2堆和栈的对比①按分配方式分:栈:栈有两种分配方式:静态分配和动态分配堆:在C中堆是动态分配和回收内存的,没有静态分配的堆。(静态分配是系统编译器完成的,比如局部变量的分配.)(动态分配是有malloc函数进行分配的,但是栈的动态分配和堆是不同的,它的动态分配也由系统编译器进行释放,不需要程序员手动管理)②申请大小的限制栈:栈是向低地址扩展的数据结构,是一块连续的内存的区域。堆:堆是向高地址扩展的数据结构,是不连续的内存区域。堆获得的空间比较灵活,也比较大。③效率:栈:由系统自动分配,速度较快,不会产生内存碎片。堆:在C中堆是由malloc分配的内存,速度比较慢,而且容易产生内存碎片,不过用起来较方便。使用堆时,频繁的用new/delete必会造成内存空间的不连续,导致造成大量碎片的产生,降低程序效率。而栈则不会有这个问题,因为栈是先进后出的队列,它们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出。 四、数据结构中的堆、栈我们在此只是了解下基本的数据结构,它们的语言实现、深入了解请参考其他资料。 4.1栈①定义:栈是限制插入和删除只能在一个位置上进行的线性表。该位置即为表的末端也叫栈顶(top)栈又叫作“先进后出表”。②基本操作:栈的基本操作包括:push(进栈)和pop(出栈)。③栈的实现:栈是一个线性表,所以栈可以用数组或者链表来实现(即栈可以由逻辑上连续的ADT实现)。在java中大部分栈的实现是使用ArrayList或者LinkedList。④性能:索引:O(n) 查找:O(n) 插入:O(1) 删除:O(1) 4.2堆①定义: 堆是一种特别的树状数据结构。堆要满足以下特征:“给定堆中任意节点P和C,若P是C的母节点,那么P的值会小于等于(或大于等于)C的值”。逻辑定义 ①定义:堆是完全二叉树,完全二叉树不一定是堆 ②堆的实现: 通过构造二叉堆(binary heap),实为二叉树的一种;由于其应用的普遍性,当不加限定时,均指该数据结构的这种实现。这种数据结构具有以下性质:①任意节点小于(或大于)它的所有后裔,最小元(或最大元)在堆的根上(堆序性)。②堆总是一棵完全树。即除了最底层,其他层的节点都被元素填满,且最底层尽可能地从左到右填入。③将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。最大堆:若母节点的值恒小于等于子节点的值,此堆称为最小堆(min heap)。最小堆:若母节点的值恒大于等于子节点的值,此堆称为最大堆(max heap)。在堆中最顶端的那一个节点,称作根节点(root node),根节点本身没有母节点(parent node)。④二叉堆的性能:索引:O(log(n))查找:O(log(n))插入:O(log(n))删除:O(log(n))删除最大值/最小值:O(1) ④应用:堆排序、优先队列。 参考资料“堆栈”的有关笔记维基百科栈和堆的区别栈、堆、静态存储区深入理解java虚拟机深入理解计算机操作系统

July 14, 2019 · 1 min · jiezi

经典计算机书籍推荐 附下载地址 PDF格式

项目地址注:书名旁边的括号为下载密码 持续更新 欢迎关注前端你不知道的JavaScript(上) (arbr)你不知道的JavaScript(中) (dwhb)你不知道的JavaScript(下) (svi8)JavaScript高级程序设计 (t8x6)高性能JavaScript (tqn7)ES6标准入门JavaScript语言精粹 (er8r)计算机体系结构计算机体系结构:量化研究方法 (9ep1)操作系统深入理解计算机系统(CSAPP) (ped8)操作系统精髓与设计原理 (ghcp)现代操作系统 (kpqq)计算机组成原理计算机组成与设计 (qapc)编译原理计算机系统要素 (6vtx)计算机程序的构造和解释(SICP) (9w4d)计算机网络图解HTTP (46td)计算机网络-自顶向下方法 (stia)软件工程代码大全2 (h13w)重构 (33ii)数据结构与算法算法导论 (j4b4)算法4 (3gek)NodeJS深入浅出node.js (eced)Cc程序设计语言 (316m)其他编码 (qp69)

March 28, 2019 · 1 min · jiezi

翻译书籍《计算机科学与数学》

一、概述曾几何时,利用Google搜索某问题的时候,意外地接触到了一个网站:https://www.gitbook.com/。一个在线编辑书籍、文章的文章,具体描述可以去其网站观看。该网站旧版地址:legacy.gitbook.com.刚工作不到一年的时候,接触到公司的商业项目,逐步意识到编程说难不难,说不难也难。之前看文章说学计算机绕不开的两项技能:英语和数学,在此期间深刻体会到了其重要性。尤其是数学,我发现一般开发只需要中学数学知识就够了,尤其是高中数学,当年只是为了高考,不知有何用,现在真要感谢高数的数学老师。当然搞人工智能只有高中数学是不够的,我想从事人工智能行业的朋友应该对大学数学的作用有更深刻的认识。编程中两项核心能力——抽象和逻辑能力,都可以通过扎实的数学训练得到加强。为什么说编程的核心能力也是难点所在是抽象和逻辑能力呢?数据结构与算法是大部分程序员头痛的地方,数据结构即抽象,是对现实世界的人和物的抽象表示;算法即逻辑。还有同样令人头疼的设计模式不也是因为太抽象了吗? 还有一旦涉及到软件系统设计,这也是抽象。二、下面通过例子体会,高中数学在计算机的应用。比如,编程语言的循环和递归,不就是数学归纳法的体现吗?再如几个常见数学概念在计算机和软件开发中的体现,1.函数数学函数三要素:定义域、对应法则、值域。对应于编程语言中的函数:形式参数、函数主体(逻辑、计算规则)、返回值。2.命题(1)命题的真假对应分支语句的真与假分支语句判断条件有无遗漏,从以下两点分析:a.条件有没有遗漏分支语句范围要完整,才不会有遗漏,导致逻辑错误。另外还要注意else if语句是排他的。举例,else if 语句:if(x > 60){……}else if(x > 40){……}else if(x > 20){……}b.条件有没有重复三、结语铺垫了那么长,就是想强调数学的趣味性和重要性。因此,本人就特意查找到了专门讲解有关计算机科学的数学的课程,准备好好学习,并翻译其教材,即精读。翻译工具即Gitbook。初步成果展示链接:https://finit-xu.gitbook.io/m…。也可以点击阅读原文查看课程详情。

March 12, 2019 · 1 min · jiezi

国内高校课程资源汇总 2019.3

以下是由广大网友整理的,国内某一高校的课程资源汇总。浙江大学课程攻略共享计划中国科学技术大学课程资源北京大学 EECS 课程资源上海交通大学软件学院课程资源代码(大作业、Lab)课件北京林业大学信息学院课程攻略

March 6, 2019 · 1 min · jiezi

别被官方文档迷惑了!这篇文章帮你详解yarn公平调度

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~本文由@edwinhzhang发表于云+社区专栏FairScheduler是yarn常用的调度器,但是仅仅参考官方文档,有很多参数和概念文档里没有详细说明,但是这些参明显会影响到集群的正常运行。本文的主要目的是通过梳理代码将关键参数的功能理清楚。下面列出官方文档中常用的参数:yarn.scheduler.fair.preemption.cluster-utilization-thresholdThe utilization threshold after which preemption kicks in. The utilization is computed as the maximum ratio of usage to capacity among all resources. Defaults to 0.8f.yarn.scheduler.fair.update-interval-msThe interval at which to lock the scheduler and recalculate fair shares, recalculate demand, and check whether anything is due for preemption. Defaults to 500 ms.maxAMSharelimit the fraction of the queue’s fair share that can be used to run application masters. This property can only be used for leaf queues. For example, if set to 1.0f, then AMs in the leaf queue can take up to 100% of both the memory and CPU fair share. The value of -1.0f will disable this feature and the amShare will not be checked. The default value is 0.5f.minSharePreemptionTimeoutnumber of seconds the queue is under its minimum share before it will try to preempt containers to take resources from other queues. If not set, the queue will inherit the value from its parent queue.fairSharePreemptionTimeoutnumber of seconds the queue is under its fair share threshold before it will try to preempt containers to take resources from other queues. If not set, the queue will inherit the value from its parent queue.fairSharePreemptionThresholdIf the queue waits fairSharePreemptionTimeout without receiving fairSharePreemptionThresholdfairShare resources, it is allowed to preempt containers to take resources from other queues. If not set, the queue will inherit the value from its parent queue.在上述参数描述中,timeout等参数值没有给出默认值,没有告知不设置会怎样。minShare,fairShare等概念也没有说清楚,很容易让人云里雾里。关于这些参数和概念的详细解释,在下面的分析中一一给出。FairScheduler整体结构 图(1) FairScheduler 运行流程图公平调度器的运行流程就是RM去启动FairScheduler,SchedulerDispatcher两个服务,这两个服务各自负责update线程,handle线程。update线程有两个任务:(1)更新各个队列的资源(Instantaneous Fair Share),(2)判断各个leaf队列是否需要抢占资源(如果开启抢占功能)handle线程主要是处理一些事件响应,比如集群增加节点,队列增加APP,队列删除APP,APP更新container等。FairScheduler类图图(2) FairScheduler相关类图队列继承模块:yarn通过树形结构来管理队列。从管理资源角度来看,树的根节点root队列(FSParentQueue),非根节点(FSParentQueue),叶子节点(FSLeaf),app任务(FSAppAttempt,公平调度器角度的App)都是抽象的资源,它们都实现了Schedulable接口,都是一个可调度资源对象。它们都有自己的fair share(队列的资源量)方法(这里又用到了fair share概念),weight属性(权重)、minShare属性(最小资源量)、maxShare属性(最大资源量),priority属性(优先级)、resourceUsage属性(资源使用量属性)以及资源需求量属性(demand),同时也都实现了preemptContainer抢占资源的方法,assignContainer方法(为一个ACCEPTED的APP分配AM的container)。public interface Schedulable { /** * Name of job/queue, used for debugging as well as for breaking ties in * scheduling order deterministically. / public String getName(); /* * Maximum number of resources required by this Schedulable. This is defined as * number of currently utilized resources + number of unlaunched resources (that * are either not yet launched or need to be speculated). / public Resource getDemand(); /* Get the aggregate amount of resources consumed by the schedulable. / public Resource getResourceUsage(); /* Minimum Resource share assigned to the schedulable. / public Resource getMinShare(); /* Maximum Resource share assigned to the schedulable. / public Resource getMaxShare(); /* Job/queue weight in fair sharing. / public ResourceWeights getWeights(); /* Start time for jobs in FIFO queues; meaningless for QueueSchedulables./ public long getStartTime(); /** Job priority for jobs in FIFO queues; meaningless for QueueSchedulables. / public Priority getPriority(); /* Refresh the Schedulable’s demand and those of its children if any. / public void updateDemand(); /* * Assign a container on this node if possible, and return the amount of * resources assigned. / public Resource assignContainer(FSSchedulerNode node); /* * Preempt a container from this Schedulable if possible. / public RMContainer preemptContainer(); /* Get the fair share assigned to this Schedulable. / public Resource getFairShare(); /* Assign a fair share to this Schedulable. / public void setFairShare(Resource fairShare);}队列运行模块:从类图角度描述公平调度的工作原理。SchedulerEventDispatcher类负责管理handle线程。FairScheduler类管理update线程,通过QueueManager获取所有队列信息。我们从Instantaneous Fair Share 和Steady Fair Share 这两个yarn的基本概念开始进行代码分析。Instantaneous Fair Share & Steady Fair ShareFair Share指的都是Yarn根据每个队列的权重、最大,最小可运行资源计算的得到的可以分配给这个队列的最大可用资源。本文描述的是公平调度,公平调度的默认策略FairSharePolicy的规则是single-resource,即只关注内存资源这一项指标。Steady Fair Share:是每个队列内存资源量的固定理论值。Steady Fair Share在RM初期工作后不再轻易改变,只有后续在增加节点(addNode)时才会重新计算。RM的初期工作也是handle线程把集群的每个节点添加到调度器中(addNode)。Instantaneous Fair Share:是每个队列的内存资源量的实际值,是在动态变化的。yarn里的fair share如果没有专门指代,都是指的的Instantaneous Fair Share。1 Steady Fair Share计算方式 图(3) steady fair share 计算流程handle线程如果接收到NODE_ADDED事件,会去调用addNode方法。 private synchronized void addNode(RMNode node) { FSSchedulerNode schedulerNode = new FSSchedulerNode(node, usePortForNodeName); nodes.put(node.getNodeID(), schedulerNode); //将该节点的内存加入到集群总资源 Resources.addTo(clusterResource, schedulerNode.getTotalResource()); //更新available资源 updateRootQueueMetrics(); //更新一个container的最大分配,就是UI界面里的MAX(如果没有记错的话) updateMaximumAllocation(schedulerNode, true); //设置root队列的steadyFailr=clusterResource的总资源 queueMgr.getRootQueue().setSteadyFairShare(clusterResource); //重新计算SteadyShares queueMgr.getRootQueue().recomputeSteadyShares(); LOG.info(“Added node " + node.getNodeAddress() + " cluster capacity: " + clusterResource); }recomputeSteadyShares 使用广度优先遍历计算每个队列的内存资源量,直到叶子节点。 public void recomputeSteadyShares() { //广度遍历整个队列树 //此时getSteadyFairShare 为clusterResource policy.computeSteadyShares(childQueues, getSteadyFairShare()); for (FSQueue childQueue : childQueues) { childQueue.getMetrics().setSteadyFairShare(childQueue.getSteadyFairShare()); if (childQueue instanceof FSParentQueue) { ((FSParentQueue) childQueue).recomputeSteadyShares(); } } }computeSteadyShares方法计算每个队列应该分配到的内存资源,总体来说是根据每个队列的权重值去分配,权重大的队列分配到的资源更多,权重小的队列分配到得资源少。但是实际的细节还会受到其他因素影响,是因为每队列有minResources和maxResources两个参数来限制资源的上下限。computeSteadyShares最终去调用computeSharesInternal方法。比如以下图为例:图中的数字是权重,假如有600G的总资源,parent=300G,leaf1=300G,leaf2=210G,leaf3=70G。图(4) yarn队列权重computeSharesInternal方法概括来说就是通过二分查找法寻找到一个资源比重值R(weight-to-slots),使用这个R为每个队列分配资源(在该方法里队列的类型是Schedulable,再次说明队列是一个资源对象),公式是steadyFairShare=R * QueueWeights。computeSharesInternal是计算Steady Fair Share 和Instantaneous Fair Share共用的方法,根据参数isSteadyShare来区别计算。之所以要做的这么复杂,是因为队列不是单纯的按照比例来分配资源的(单纯按权重比例,需要maxR,minR都不设置。maxR的默认值是0x7fffffff,minR默认值是0)。如果设置了maxR,minR,按比例分到的资源小于minR,那么必须满足minR。按比例分到的资源大于maxR,那么必须满足maxR。因此想要找到一个R(weight-to-slots)来尽可能满足:R(Queue1Weights + Queue2Weights+…+QueueNWeights) <=totalResourceRQueueWeights >= minShareRQueueWeights <= maxShare注:QueueNWeights为队列各自的权重,minShare和maxShare即各个队列的minResources和maxResourcescomputcomputeSharesInternal详细来说分为四个步骤:确定可用资源:totalResources = min(totalResources-takenResources(fixedShare), totalMaxShare)确定R上下限二分查找法逼近R使用R设置fair Share private static void computeSharesInternal( Collection<? extends Schedulable> allSchedulables, Resource totalResources, ResourceType type, boolean isSteadyShare) { Collection<Schedulable> schedulables = new ArrayList<Schedulable>(); //第一步 //排除有固定资源不能动的队列,并得出固定内存资源 int takenResources = handleFixedFairShares( allSchedulables, schedulables, isSteadyShare, type); if (schedulables.isEmpty()) { return; } // Find an upper bound on R that we can use in our binary search. We start // at R = 1 and double it until we have either used all the resources or we // have met all Schedulables’ max shares. int totalMaxShare = 0; //遍历schedulables(非固定fixed队列),将各个队列的资源相加得到totalMaxShare for (Schedulable sched : schedulables) { int maxShare = getResourceValue(sched.getMaxShare(), type); totalMaxShare = (int) Math.min((long)maxShare + (long)totalMaxShare, Integer.MAX_VALUE); if (totalMaxShare == Integer.MAX_VALUE) { break; } } //总资源要减去fiexd share int totalResource = Math.max((getResourceValue(totalResources, type) - takenResources), 0); //队列所拥有的最大资源是有集群总资源和每个队列的MaxResource双重限制 totalResource = Math.min(totalMaxShare, totalResource); //第二步:设置R的上下限 double rMax = 1.0; while (resourceUsedWithWeightToResourceRatio(rMax, schedulables, type) < totalResource) { rMax = 2.0; } //第三步:二分法逼近合理R值 // Perform the binary search for up to COMPUTE_FAIR_SHARES_ITERATIONS steps double left = 0; double right = rMax; for (int i = 0; i < COMPUTE_FAIR_SHARES_ITERATIONS; i++) { double mid = (left + right) / 2.0; int plannedResourceUsed = resourceUsedWithWeightToResourceRatio( mid, schedulables, type); if (plannedResourceUsed == totalResource) { right = mid; break; } else if (plannedResourceUsed < totalResource) { left = mid; } else { right = mid; } } //第四步:使用R值设置,确定各个非fixed队列的fairShar,意味着只有活跃队列可以分资源 // Set the fair shares based on the value of R we’ve converged to for (Schedulable sched : schedulables) { if (isSteadyShare) { setResourceValue(computeShare(sched, right, type), ((FSQueue) sched).getSteadyFairShare(), type); } else { setResourceValue( computeShare(sched, right, type), sched.getFairShare(), type); } } }(1) 确定可用资源handleFixedFairShares方法来统计出所有fixed队列的fixed内存资源(fixedShare)相加,并且fixed队列排除掉不得瓜分系统资源。yarn确定fixed队列的标准如下: private static int getFairShareIfFixed(Schedulable sched, boolean isSteadyShare, ResourceType type) { //如果队列的maxShare <=0 则是fixed队列,fixdShare=0 if (getResourceValue(sched.getMaxShare(), type) <= 0) { return 0; } //如果是计算Instantaneous Fair Share,并且该队列内没有APP再跑, // 则是fixed队列,fixdShare=0 if (!isSteadyShare && (sched instanceof FSQueue) && !((FSQueue)sched).isActive()) { return 0; } //如果队列weight<=0,则是fixed队列 //如果对列minShare <=0,fixdShare=0,否则fixdShare=minShare if (sched.getWeights().getWeight(type) <= 0) { int minShare = getResourceValue(sched.getMinShare(), type); return (minShare <= 0) ? 0 : minShare; } return -1; }(2)确定R上下限R的下限为1.0,R的上限是由resourceUsedWithWeightToResourceRatio方法来确定。该方法确定的资源值W,第一步中确定的可用资源值T:W>=T时,R才能确定。//根据R值去计算每个队列应该分配的资源 private static int resourceUsedWithWeightToResourceRatio(double w2rRatio, Collection<? extends Schedulable> schedulables, ResourceType type) { int resourcesTaken = 0; for (Schedulable sched : schedulables) { int share = computeShare(sched, w2rRatio, type); resourcesTaken += share; } return resourcesTaken; } private static int computeShare(Schedulable sched, double w2rRatio, ResourceType type) { //share=Rweight,type是内存 double share = sched.getWeights().getWeight(type) * w2rRatio; share = Math.max(share, getResourceValue(sched.getMinShare(), type)); share = Math.min(share, getResourceValue(sched.getMaxShare(), type)); return (int) share; }(3)二分查找法逼近R满足下面两个条件中的一个即可终止二分查找:W == T(步骤2中的W和T)超过25次(COMPUTE_FAIR_SHARES_ITERATIONS)(4)使用R设置fair share设置fair share时,可以看到区分了Steady Fair Share 和Instantaneous Fair Share。 for (Schedulable sched : schedulables) { if (isSteadyShare) { setResourceValue(computeShare(sched, right, type), ((FSQueue) sched).getSteadyFairShare(), type); } else { setResourceValue( computeShare(sched, right, type), sched.getFairShare(), type); } }2 Instaneous Fair Share计算方式图(5)Instaneous Fair Share 计算流程该计算方式与steady fair的计算调用栈是一致的,最终都要使用到computeSharesInternal方法,唯一不同的是计算的时机不一样。steady fair只有在addNode的时候才会重新计算一次,而Instantaneous Fair Share是由update线程定期去更新。此处强调的一点是,在上文中我们已经分析如果是计算Instantaneous Fair Share,并且队列为空,那么该队列就是fixed队列,也就是非活跃队列,那么计算fair share时,该队列是不会去瓜分集群的内存资源。而update线程的更新频率就是由 yarn.scheduler.fair.update-interval-ms来决定的。private class UpdateThread extends Thread { @Override public void run() { while (!Thread.currentThread().isInterrupted()) { try { //yarn.scheduler.fair.update-interval-ms Thread.sleep(updateInterval); long start = getClock().getTime(); // 更新Instantaneous Fair Share update(); //抢占资源 preemptTasksIfNecessary(); long duration = getClock().getTime() - start; fsOpDurations.addUpdateThreadRunDuration(duration); } catch (InterruptedException ie) { LOG.warn(“Update thread interrupted. Exiting.”); return; } catch (Exception e) { LOG.error(“Exception in fair scheduler UpdateThread”, e); } } } }3 maxAMShare意义handle线程如果接收到NODE_UPDATE事件,如果(1)该node的机器内存资源满足条件,(2)并且有ACCEPTED状态的Application,那么将会为该待运行的APP的AM分配一个container,使该APP在所处的queue中跑起来。但在分配之前还需要一道检查canRuunAppAM。能否通过canRuunAppAM,就是由maxAMShare参数限制。 public boolean canRunAppAM(Resource amResource) { //默认是0.5f float maxAMShare = scheduler.getAllocationConfiguration().getQueueMaxAMShare(getName()); if (Math.abs(maxAMShare - -1.0f) < 0.0001) { return true; } //该队的maxAMResource=maxAMShare * fair share(Instantaneous Fair Share) Resource maxAMResource = Resources.multiply(getFairShare(), maxAMShare); //amResourceUsage是该队列已经在运行的App的AM所占资源累加和 Resource ifRunAMResource = Resources.add(amResourceUsage, amResource); //查看当前ifRunAMResource是否超过maxAMResource return !policy .checkIfAMResourceUsageOverLimit(ifRunAMResource, maxAMResource); }上面代码我们用公式来描述:队列中运行的APP为An,每个APP的AM占用资源为RACCEPTED状态(待运行)的APP的AM大小为R1队列的fair share为QueFS队列的maxAMResource=maxAMShare * QueFSifRunAMResource=A1.R+A2.R+…+An.R+R1ifRunAMResource > maxAMResource,则该队列不能接纳待运行的APP之所以要关注这个参数,是因为EMR很多客户在使用公平队列时会反映集群的总资源没有用满,但是还有APP在排队,没有跑起来,如下图所示:图(6) APP阻塞实例公平调度默认策略不关心Core的资源,只关心Memory。图中Memory用了292G,还有53.6G的内存没用,APP就可以阻塞。原因就是default队列所有运行中APP的AM资源总和超过了(345.6 * 0.5),导致APP阻塞。总结通过分析fair share的计算流程,搞清楚yarn的基本概念和部分参数,从下面的表格对比中,我们也可以看到官方的文档对概念和参数的描述是比较难懂的。剩余的参数放在第二篇-公平调度之抢占中分析。 官方描述总结Steady Fair ShareThe queue’s steady fair share of resources. These shares consider all the queues irrespective of whether they are active (have running applications) or not. These are computed less frequently and change only when the configuration or capacity changes.They are meant to provide visibility into resources the user can expect, and hence displayed in the Web UI.每个非fixed队列内存资源量的固定理论值。Steady Fair Share在RM初期工作后不再轻易改变,只有后续在增加节点改编配置(addNode)时才会重新计算。RM的初期工作也是handle线程把集群的每个节点添加到调度器中(addNode)。Instantaneous Fair ShareThe queue’s instantaneous fair share of resources. These shares consider only actives queues (those with running applications), and are used for scheduling decisions. Queues may be allocated resources beyond their shares when other queues aren’t using them. A queue whose resource consumption lies at or below its instantaneous fair share will never have its containers preempted.每个非fixed队列(活跃队列)的内存资源量的实际值,是在动态变化的,由update线程去定时更新队列的fair share。yarn里的fair share如果没有专门指代,都是指的的Instantaneous Fair Share。yarn.scheduler.fair.update-interval-msThe interval at which to lock the scheduler and recalculate fair shares, recalculate demand, and check whether anything is due for preemption. Defaults to 500 ms.update线程的间隔时间,该线程的工作是1更新fair share,2检查是否需要抢占资源。maxAMSharelimit the fraction of the queue’s fair share that can be used to run application masters. This property can only be used for leaf queues. For example, if set to 1.0f, then AMs in the leaf queue can take up to 100% of both the memory and CPU fair share. The value of -1.0f will disable this feature and the amShare will not be checked. The default value is 0.5f.队列所有运行中的APP的AM资源总和必须不能超过maxAMShare * fair share问答如何将yarn 升级到特定版本?相关阅读Yarn与MesosSpark on Yarn | Spark,从入门到精通YARN三大模块介绍 【每日课程推荐】机器学习实战!快速入门在线广告业务及CTR相应知识 ...

October 8, 2018 · 7 min · jiezi

你大概走了假敏捷:《手绘敏捷宝典》在此,还不来收!

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~本文由薄玉桴发表于云+社区专栏今天你敏捷了没有?“敏捷”在互联网和软件开发领域从涓涓细流逐渐演变为行业潮流,往小了说是改进了开发方法,往大了说是革了瀑布流式的命——把产品开发引向了快速迭代、小步快跑的路线上。我们使用 tapd 写 feature,流转、跟踪任务,言必谈敏捷,然而我们是否真的走对了敏捷?(注:tapd 是腾讯内部的敏捷项目管理系统) 。1.朋友,你听说过敏捷么?2.离开敏捷工具,我们怎么敏?3.设计也要介入敏捷流程?4.敏捷跟文档是对立的?5.我这有个几百亿的大项目,怎么敏?6.尽信书,不如无书。一、朋友,你听说过敏捷么?程序员说,要有敏捷从敏捷的滥觞看去,比起方法,这玩意貌似更像一个宗教(笑)。千禧之初,美国在计算机行业已经走了几十年,瀑布流、螺旋模型、快速迭代…各种各样的软件开发流程雨后春笋各领风骚一段时间。虽然不断变化和完善,但互联网的加速发展让传统方法显得笨重,难以快速适应变化。有十七个程序员(程序员改变世界)在美国犹他州的一个风景区开了个碰头会,找到了一个团队耦合度高,流程极其灵活的方法,他们把它称为agile program development。这十七个人如同开宗立派的长老,在会议之后给自己起了个名字“敏捷联盟”,他们不仅赋予了新方法名字,还有宣言,甚至纲领。盐湖城- snowbird(敏捷联盟成立地——雪鸟滑雪场)中文版的“敏捷宣言”。在建立于2002年3月的 《Manifesto for Agile Software Development》里你可以找到几十种语言的“敏捷宣言”。另外,长老们还制定了12原则,作为福音传播。显而易见,敏捷是绝对的结果导向,去文档化,去流程化,高效沟通和合作是究极奥义。看起来是个很不错的方法,文档不重要了,流程不重要了,大家聚在一起说一说就可以了不是吗?太棒了,感觉可以从繁重的文书工作中解脱出来了呢。失之东隅收之桑榆。一处的方便一定意味着另外什么地方以其他方式运行着简化掉的部分。去文档,敏捷管理者需要维护更为精细的需求池;去流程,口头沟通成为常态,对团队的耦合度要求更高。胖友,这里有一份教义,你要不要听一下。初识敏捷,有一些概念需要了解,如果你是老司机,跳过这部分,阿敏。agile:迅速,敏捷。这是敏捷的理念也是精髓:迅速响应需求,快速反馈结果。agile 的引入像一股活水冲击着老气横秋的瀑布流模型,速度上跑赢几条街。sprint:字面意思是短跑冲刺,一个开发阶段被认为是一次冲刺,一个个 sprint 首位相连,构成一个项目。Scrum:指的是英式橄榄球中一股脑争球这一战术或行为。scrum 即为这样一种方式,大家一拥而上,团队是球员,球是产品目标,人员环环相扣,围绕着产品目标进行工作。这里面多少有点“统筹法”的影子,人员深入协作以达到最优化效果。Product Backlog:backlog 即需求池。待办事项列表。Backlog 里面写什么:1.待开发任务。2.任务优先级。敏捷需要维护一份详尽的需求列表。这份列表常常要求 scrum 持有人(一般是产品经理)对所有待开发事项有深入了解,并且能够把待开发事项分解成更为细致的任务(或者跟敏捷教练一起,后面我们会再次提到敏捷教练)story board:很多领域都有故事板的概念,交互领域里,用故事板表述用户场景、电影领域里故事板用来更具体地描述分镜。在开发领域,故事版是任务流转的可视化窗口,一般有“待开发”“开发中”“待测试”“返工”“待发布”几个区块,所有任务由任务操作者负责流转至于下一个步骤,这样任何一个人项目成员都能看到任务的完成情况。一个app使用情景故事版在开发中,故事板展现所有需求的工作流burn down chart:燃尽图一个 sprint 内,人/时是一个比较固定的值。在这个时间框架充分安排开发任务,每天进行时间结算,绘制时间燃尽图。项目成员通过燃尽图获知时间进展,若项目燃尽所用时间与预期时间契合,则需求时间预估和安排合理,若不契合则需要在下一个 sprint 进行调整。名词听起来都玄乎乎的,很符合开宗立派的气质。这些概念定义了敏捷各个环节的工作,这些流程和节点是敏捷开展的基础和保障。二、离开敏捷工具,我们怎么敏?一个误区:我们用了敏捷管理工具,就敏捷了随着敏捷在行业内的不断融入,各种工具产品层出不穷。国外jira、redmine,Axosoft ,国内的leangoo 、禅道,三大家则都有自研的工具,百度的icafe,阿里的aone,我鹅自研tapd。(数据来源:“2016中国开发者白皮书”)我们在 tapd 上建迭代,建需求,研发、测试等着收到需求流转的邮件之后开始干活…任务在测试和研发之间流转,bug 提给研发,研发解决 bug …..我们宣称:我们敏捷化了!我们习惯于敏捷软件的便利,拉群解决一切,然而却丧失了敏捷的初衷,scrum 的本意。Jira的名字来自于哥斯拉假设我们没有任何项目协同软件,敏捷怎么实施?设定一个环境,现在没有任何协同工具可用,但是所有人都坐在一起。有人站起来说,既然这样,我们不如敏捷吧!敏捷工具消失了敏捷路径里必须有一个项目持有者,制定规划并把握项目走向。这位产品汪我看你骨骼惊奇,你就担负起这个责任吧。另外还有一个关键人物 SM(别想歪)。SM 全称 scrum master,中文称敏捷教练。一般说来,SM 需要由对技术开发以及当前项目明晰的技术经理担任。虽然缺少线上工具,但至少要准备一些简单材料:一卷双面胶+白纸或一沓便利贴;笔,一面平坦的墙或一块黑板。如果还有电脑可用,excel 或者 word,甚至写字板都可以,没有电脑那就白纸好了,总之你得找个地方写下你的需求池(backlog)需求池示例(任务名称、平台、详细描述、优先级按照P0-PX逐渐递减)确定一个 sprint 周期的自然天。可以用月/旬/周等时间概念作为周期,我们选择一周(五个工作日)作为一个 sprint 周期。按照优先级,从需求池中拉出你认为应该加入你们一穷二白的第一个 sprint 里面去的需求,别太贪心,大概觉得差不多一周左右的开发量就够了。拉上SM桑单独开一次小会。当然不是让你俩傻站着,你俩要开会你们一起通览需求,SM 桑根据经验对需求先行分解一遍,比如某需求在开发层面需要分解为 ABC 三部分,这三部分就形成三个开发任务。分解完成后,你得到了一个比较详细的待开发列表。正式开始一个 sprint 开始之前,产品、研发、测试需要一同开一次 scrum 会议,共同讨论本次 sprint 的功能点。会上讨论什么:1.需求讨论或技术讨论;2.成员预估需求所需开发时间;3.需求是否match人力时间,需求排入sprint;4.交流一下感情。每个任务的预估时间在最后由敏捷教练综合判定scrum 会后你的工作:1.整理这个 sprint 内的需求列表;2.整理每个需求的预期开发时间;3.撰写故事版上的小纸条;4.把小纸条贴到故事版上;5.制作一个燃尽图。一个改良版的小纸条,写明开发者、任务描述、预估时间和每日燃尽时间故事版布局如下:一个标准的故事版:最开始所有的小纸条都在“待开发”一栏到此为止,你可以开始 run 起一个 sprint 。以为这就完事了?天真。接下来你必须来参加每日举行的项目短会。这个环节在 agile 中非常关键,是 agile 的日常修炼。为了缩减会议时间,我们一般站着开——所以也叫“站会”,早上上班后或晚上下班前,抽出十到十五分钟时间,完成它。每日站会站会都有什么人参加:1.你(项目持有者)2.SM3.其他 scrum 成员站会干什么:1.昨天大家分别做了什么事,遇到了什么问题,如何解决或寻求解决方案;2.昨天任务的完成状态,剩余多少时间,是否需要进行时间修正(增加时间或减少时间),把已完成的任务流转到下一环节(把纸条从一个item内撕下,贴到下一个item里去);任务进行中,小纸条的示例3.功能测试后是否有返工;4.交流一下感情。站会之后你的工作:绘制燃尽图。一个燃尽图的示例:正常的 sprint 的任务时间是随着 sprint 的进程逐渐减少的周而复始,完成了一个 sprint 后,你们开了第二次 scrum 会。这时议题多了一项:复盘上一个 sprint。任务未能燃尽;研发返工过多;测试需求淤积…..针对问题讨论解决方案,根据实际情况进行下一个 sprint 的任务安排。自此,我们在没有任何敏捷工具的帮助下,开始了敏捷的旅程。说起来agile developing 本来就是排斥文档的作业方式,为一个小轻快的方法制作一套严谨庞大的工具,基本也算违背了元老们的初衷了吧,科科。三、设计师在敏捷中如何介入?我们正在使用或者听过的一些流程方法——不单敏捷,瀑布流,迭代式,结对开发,精益开发….似乎都不关设计师什么事。既然开发团队抱团敏捷了,设计,这个在产品流程中必不可少而工作内容相对独立的角色,要怎么介入敏捷呢?一种思路是,设计拥有自己的敏捷流程。设计师作为一个 scrum 存在,以从上游获取的需求进行 sprint 。另一种思路,是把设计和测试完全纳入到团队中来,一起进行 scrum 的合作。这样的话,UI工作至少要比开发工作前移至少半个 sprint 。有请产品经理(项目持有者)出场。很好,我们有了一个设计师项目持有者将需求分为“ UI 支持”和“非 UI 支持”两类。我们将小纸条扩展一下。多出来 UI 前置部分的小纸条U I设计师参与到 scrum 会中。对于需要 UI 支持的需求,设计师给出一个 UI 制作的时间预估。项目持有者将这部分时间加到扩展小纸条上去。在一个 sprint 中,设计师的工作跟研发的工作分别进行。当设计师将某一需求完成时,将小纸条的 UI 部分撕下,汇入到“”待开发”中去。一个已经完成了 UI 设计的小纸条示例四、敏捷不需要文档吗?一切为快服务的敏捷特别适合初创团队使用。它能把团队人员紧密结合在一起,高效而有序地输出产能。而常规高效的版本输出往往是初创团队高速发展的第一要务。敏捷了一段时间之后,产品进入正轨,项目拿到拨款,公司拿到投资,你们要扩大团队规模,新入职的同事想了解下产品和技术细节,你告诉TA:你要不翻下 backlog 看看?这个实现你要不看一下代码?这个字段我也不记得有没有了….你抓包看下?新同事一脸懵逼,难道咱们没有文档吗?你自豪地指出:“我们是敏捷团队。”十几个人八九条枪的阶段之后,产品趋于稳定,团队逐步扩大。无论从内部协调还是外部沟通上对产品流程的正规化和文档化要求与日俱增。从短期收益上看,文档对于敏捷开发是非必须品,并且很有可能会拖慢进度。在一个 sprint 中,口头沟通显然效率更高,每个人都有精确到工时的任务,没人有等待文档更新的时间。强调文档就等于放弃灵活性。从长期和宏观上看,文档对于敏捷团队和敏捷的实施利大于弊——节省在一些常规问题上的沟通成本,同时降低错误的发生概率。对于一个将要长期实施敏捷的 团队来讲,文档让后续的工作效率更高。一个以讹传讹的过程这样一个功在当代利在千秋的好事,当然要做。那么——谁来维护文档,怎么维护?我们挑选几个重要的文档:产品文档、概要设计、接口文档产品文档:不好意思内个产品经理你过来下。虽然你要维护 backlog 、跟 SM 分解需求、开 scrum 会、写小纸条、开站会、画燃尽图、还有什么外部沟通啊,写 PPT 啊,绞尽脑汁想规划啊……你还得认真把这个文档维护好。对又是你产品文档包括:1.需求;2.加入日期;3.开发版本;4.呈现和详细方案在非敏捷开发流程中,文档在评审会后完善并更新,形成一个给研发参考的实现目标。在敏捷中,需求本身在 sprint 周期内不断完善,你可以在一个 sprint 之后将文档补全。概要设计:敏捷的常规迭代中,概要设计不是一个必须的文档。但全新项目、重构以及重大新功能则必须输出概要设计文档。研发 leader 责无旁贷,这个落你身上了。接口文档:必要且重要。包括接口说明、字段定义、字段类型、值定义、数据上报、错误码等。一般来说约定之后由接口开发者更新文档,如果你们没有云端存储的能力,至少咱们人手一份,定期更新。长久来看,文档是提高效率的一大利器虽然《宣言》中明确地放低了文档的地位(“工作的软件大于详尽的文档”),敏捷强调互动和变化,以及对变化的及时响应。诚然文档恰恰做不到如此灵活。但敏捷真的完全排斥文档吗?文档的时效性和灵活性远低于口头沟通,但却有它实在的好处。1.空间上,文档传播范围更广。规范化和常规化的内容形成文档可以大大减少沟通成本。尤其在多个系统协作的情况下,跨 scrum 、跨团队甚至跨部门的沟通时有发生,文档的重要性和便捷性不言而喻。2.时间上,文档流传性更好。团队不是一成不变的,有人离开有人加入。更新换代中,新人快速了解系统,老兵传承研发理念;在更大的时间跨度上,团队可能成为忒修斯之船,文档的存在就是对产品历程的完整追溯,你将不用他人帮助就可以了解到产品的大部分面貌甚至全貌。五、大项目怎么引入敏捷?看起来敏捷方法特别适合产品常规迭代。有一种可能性是,你的产品需要插入一个巨无霸模块,与其说是模块倒不如说它几乎可以成为一个产品了。你想了想,这么大个项目怎么说产品、设计、研发、测试全情投入也得个一两个月。还能走敏捷吗?注意你的项目时间。有 deadline 的 scrum 是带着镣铐跳迪斯科,时间节点关乎 sprint 的大小。大项目敏捷之前,先得不敏捷几步。可能会发生一到多次需求讨论会。团队必须不厌其烦地理解需求或修正产品经理“天真的幻想”,产品经理使用不断完善的原型同团队进(tao)行( jia )沟( huan )通( jia )。在最后的产品评审之前,至少敲定产品框架和大部分细节。这次评审邀请项目成员和所有协同团队,除了敲定的产品功能,技术上需要得到一些初步结论(比如“能不能做”。事实上,产品经理应该在产品规划阶段就知会协同团队将要做什么)。接下来进行概要设计(新产品、重构、重大新功能必须进行概要设计)。技术评审邀请除设计以外的项目成员和协同团队参会。大项目敏捷中:1.将 deadline 之前的时间分解为多个 sprint 。(deadline 之前必须留出一定“出血时间”用以解决时间预估不足的任务、返工任务以及 bug )2.将所有需求分解成任务,开一次全局 scrum 会。预估时间之后,分散任务到各个 sprint 中。在时间较紧的情况下,sprint 的容量就要相应增加。一个需要加班的 sprint3.进入敏捷流程,常规 scrum 会、站会,燃尽图,故事版。未完成任务在 scrum 会上重新预估时间,滚入新 sprint 内,以此类推(按时完成 sprint 内的任务是目标。实在不行我们还有“出血时间”呢)4.别忘了文档。虽然被推崇备至,但敏捷并不是完美的开发方法。敏捷的最大的优势是灵活,而造成敏捷问题的根源也正是灵活。文末再总结本文重点:1.敏捷是一种流程、方法、理念,甚至信仰。2 用了敏捷管理软件不一定就是敏捷。敏捷的初衷是团队成员能够更加紧密地配合完成工作,线上的的流转如果削弱了这种配合性,反倒背离了敏捷的本意。实际上只要有白板纸张和笔,你的团队就能开始敏捷。4.我们敏捷了,不是不要文档了。在外部交流多、世代跨度长的情况下,文档的必要性显而易见。长期的面对面沟通最终会导致低效,这也是敏捷缺陷的根源。5.设计师可以完全介入到敏捷流程中,只需要做一些细心的安排。6.大项目开发中可以走敏捷,具体问题具体分析,需要根据项目特点制定敏捷计划。(文章所有插图为笔者手绘,版权所有)问答Scrum和敏捷开发有什么区别?相关阅读胡说八道谈敏捷敏捷开发–scrum破解敏捷的密码 【每日课程推荐】机器学习实战!快速入门在线广告业务及CTR相应知识此文已由作者授权腾讯云+社区发布,更多原文请点击搜索关注公众号「云加社区」,第一时间获取技术干货,关注后回复1024 送你一份技术课程大礼包!海量技术实践经验,尽在云加社区! ...

September 24, 2018 · 1 min · jiezi

什么?强化学习竟然来源于心理学?

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~本文由罗晖发表于云+社区专栏1. Google的DQN论文2015年2月,Google在Nature上发表了一篇论文(见附件):Human-level control through deep reinforcement learning。文章描述了如何让电脑自己学会打Atari 2600电子游戏。Atari 2600是80年代风靡美国的游戏机,总共包括49个独立的游戏,其中不乏我们熟悉的Breakout(打砖块),Galaxy Invaders(小蜜蜂)等经典游戏。Google算法的输入只有游戏屏幕的图像和游戏的得分,在没有人为干预的情况下,电脑自己学会了游戏的玩法,而且在29个游戏中打破了人类玩家的记录。Google给出的深度络架构图如下:网络的左边是输入,右边是输出。 游戏屏幕的图像先经过两个卷积层(论文中写的是三个),然后经过两个全连接层, 最后映射到游戏手柄所有可能的动作。各层之间使用ReLU激活函数。2. 强化学习(Q-Learning)根据维基百科的描述,强化学习定义如下:强化学习是机器学习中的一个领域,强调如何基于环境而行动,以取得最大化的预期利益。其灵感来源于心理学中的行为主义理论,即有机体如何在环境给予的奖励或惩罚的刺激下,逐步形成对刺激的预期,产生能获得最大利益的习惯性行为。在强化学习的世界里, 算法称之为Agent, 它与环境发生交互,Agent从环境中获取状态(state),并决定自己要做出的动作(action).环境会根据自身的逻辑给Agent予以奖励(reward)。奖励有正向和反向之分。比如在游戏中,每击中一个敌人就是正向的奖励,掉血或者游戏结束就是反向的奖励。2.1. 马尔可夫决策过程现在的问题是,你如何公式化一个强化学习问题,然后进行推导呢?最常见的方法是通过马尔可夫决策过程。假设你是一个代理,身处某个环境中(例如《打砖块》游戏)。这个环境处于某个特定的状态(例如,牌子的位置、球的位置与方向,每个砖块存在与否)。人工智能可以可以在这个环境中做出某些特定的动作(例如,向左或向右移动拍子)。这些行为有时候会带来奖励(分数的上升)。行为改变环境,并带来新的状态,代理可以再执行另一个动作。你选择这些动作的规则叫做策略。通常来说,环境是随机的,这意味着下一状态也或多或少是随机的(例如,当你漏掉了球,发射一个新的时候,它会去往随机的方向)。状态与动作的集合,加上改变状态的规则,组成了一个马尔可夫决策过程。这个过程(例如一个游戏)中的一个情节(episode)形成了状态、动作与奖励的有限序列。其中 si 表示状态,ai 表示动作,ri+1 代表了执行这个动作后获得的奖励。情节以最终的状态 sn 结束(例如,「Game Over」画面)。一个马尔可夫决策过程基于马尔可夫假设(Markov assumption),即下一状态 si+1 的概率取决于现在的状态 si 和动作 ai,而不是之前的状态与动作。2.2. 折扣未来奖励(Discounted Future Reward)为了长期表现良好,我们不仅需要考虑即时奖励,还有我们将得到的未来奖励。我们该如何做呢?对于给定的马尔可夫决策过程的一次运行,我们可以容易地计算一个情节的总奖励:鉴于此,时间点 t 的总未来回报可以表达为:但是由于我们的环境是随机的,我们永远无法确定如果我们在下一个相同的动作之后能否得到一样的奖励。时间愈往前,分歧也愈多。因此,这时候就要利用折扣未来奖励来代替:在这里 是数值在0与1之间的贴现因子——奖励在距离我们越远的未来,我们便考虑的越少。我们很容易看到,折扣未来奖励在时间步骤 t 的数值可以根据在时间步骤 t+1 的相同方式表示:如果我们将贴现因子定义为 =0,那么我们的策略将会过于短浅,即完全基于即时奖励。如果我们希望平衡即时与未来奖励,那么贴现因子应该近似于 =0.9。如果我们的环境是确定的,相同的动作总是导致相同的奖励,那么我们可以将贴现因子定义为 =1。一个代理做出的好的策略应该是去选择一个能够最大化(折扣后)未来奖励的动作。2.3. Q-Learning算法描述:算法中的 是指学习率,其控制前一个 Q 值和新提出的 Q 值之间被考虑到的差异程度。尤其是,当 =1 时,两个 Qs,a 互相抵消,结果刚好和贝尔曼方程一样。我们用来更新 Qs,a 的只是一个近似,而且在早期阶段的学习中它完全可能是错误的。但是随着每一次迭代,该近似会越来越准确;而且我们还发现如果我们执行这种更新足够长时间,那么 Q 函数就将收敛并能代表真实的 Q 值。3. 卷积神经网络(CNN)在图像处理中,往往把图像表示为像素的向量,比如一个1000×1000的图像,可以表示为一个1000000的向量。在上一节中提到的神经网络中,如果隐含层数目与输入层一样,即也是1000000时,那么输入层到隐含层的参数数据为1000000×1000000=10^12,这样就太多了,基本没法训练。所以图像处理要想练成神经网络大法,必先减少参数加快速度。3.1. 局部感知卷积神经网络有两种神器可以降低参数数目,第一种神器叫做局部感知野。一般认为人对外界的认知是从局部到全局的,而图像的空间联系也是局部的像素联系较为紧密,而距离较远的像素相关性则较弱。因而,每个神经元其实没有必要对全局图像进行感知,只需要对局部进行感知,然后在更高层将局部的信息综合起来就得到了全局的信息。网络部分连通的思想,也是受启发于生物学里面的视觉系统结构。视觉皮层的神经元就是局部接受信息的(即这些神经元只响应某些特定区域的刺激)。如下图所示:左图为全连接,右图为局部连接。在上右图中,假如每个神经元只和10×10个像素值相连,那么权值数据为1000000×100个参数,减少为原来的万分之一。而那10×10个像素值对应的10×10个参数,其实就相当于卷积操作。3.2. 参数共享但其实这样的话参数仍然过多,那么就启动第二级神器,即权值共享。在上面的局部连接中,每个神经元都对应100个参数,一共1000000个神经元,如果这1000000个神经元的100个参数都是相等的,那么参数数目就变为100了。怎么理解权值共享呢?我们可以这100个参数(也就是卷积操作)看成是提取特征的方式,该方式与位置无关。这其中隐含的原理则是:图像的一部分的统计特性与其他部分是一样的。这也意味着我们在这一部分学习的特征也能用在另一部分上,所以对于这个图像上的所有位置,我们都能使用同样的学习特征。更直观一些,当从一个大尺寸图像中随机选取一小块,比如说 8x8 作为样本,并且从这个小块样本中学习到了一些特征,这时我们可以把从这个 8x8 样本中学习到的特征作为探测器,应用到这个图像的任意地方中去。特别是,我们可以用从 8x8 样本中所学习到的特征跟原本的大尺寸图像作卷积,从而对这个大尺寸图像上的任一位置获得一个不同特征的激活值。如下图所示,展示了一个3×3的卷积核在5×5的图像上做卷积的过程。每个卷积都是一种特征提取方式,就像一个筛子,将图像中符合条件(激活值越大越符合条件)的部分筛选出来。3.3. 多卷积核上面所述只有100个参数时,表明只有1个10×10的卷积核,显然,特征提取是不充分的,我们可以添加多个卷积核,比如32个卷积核,可以学习32种特征。在有多个卷积核时,如下图所示:上图右,不同颜色表明不同的卷积核。每个卷积核都会将图像生成为另一幅图像。比如两个卷积核就可以将生成两幅图像,这两幅图像可以看做是一张图像的不同的通道。如下图所示,下图有个小错误,即将w1改为w0,w2改为w1即可。下文中仍以w1和w2称呼它们。下图展示了在四个通道上的卷积操作,有两个卷积核,生成两个通道。其中需要注意的是,四个通道上每个通道对应一个卷积核,先将w2忽略,只看w1,那么在w1的某位置(i,j)处的值,是由四个通道上(i,j)处的卷积结果相加然后再取激活函数值得到的。所以,在上图由4个通道卷积得到2个通道的过程中,参数的数目为4×2×2×2个,其中4表示4个通道,第一个2表示生成2个通道,最后的2×2表示卷积核大小。3.4. Down-pooling在通过卷积获得了特征 (features) 之后,下一步我们希望利用这些特征去做分类。理论上讲,人们可以用所有提取得到的特征去训练分类器,例如 softmax 分类器,但这样做面临计算量的挑战。例如:对于一个 96X96 像素的图像,假设我们已经学习得到了400个定义在8X8输入上的特征,每一个特征和图像卷积都会得到一个 (96 − 8 + 1) × (96 − 8 + 1) = 7921 维的卷积特征,由于有 400 个特征,所以每个样例 (example) 都会得到一个 7921 × 400 = 3,168,400 维的卷积特征向量。学习一个拥有超过 3 百万特征输入的分类器十分不便,并且容易出现过拟合 (over-fitting)。为了解决这个问题,首先回忆一下,我们之所以决定使用卷积后的特征是因为图像具有一种“静态性”的属性,这也就意味着在一个图像区域有用的特征极有可能在另一个区域同样适用。因此,为了描述大的图像,一个很自然的想法就是对不同位置的特征进行聚合统计,例如,人们可以计算图像一个区域上的某个特定特征的平均值 (或最大值)。这些概要统计特征不仅具有低得多的维度 (相比使用所有提取得到的特征),同时还会改善结果(不容易过拟合)。这种聚合的操作就叫做池化 (pooling),有时也称为平均池化或者最大池化 (取决于计算池化的方法)。3.5. 多层卷积在实际应用中,往往使用多层卷积,然后再使用全连接层进行训练,多层卷积的目的是一层卷积学到的特征往往是局部的,层数越高,学到的特征就越全局化。4. DQN算法描述单纯的Q-Learning算法使用表来保存状态,一个1000×1000图像的像素状态数基本接近与无穷,故有了CNN+Q-Learning 即DQN算法,算法描述如下:5. 使用DQN训练“接砖块”游戏深度学习的开源类库比较多,比较著名的有tensorlow、caffe等。此处我们使用Tensorflow来训练游戏“接砖块”。游戏截图如下:通过点击鼠标左键、右键控制滑块的左右移动来接住小球,如果球碰到底面,则游戏结束主要python代码如下(游戏本身的代码省略,此处主要关注算法代码):#Game的定义类,此处Game是什么不重要,只要提供执行Action的方法,获取当前游戏区域像素的方法即可class Game(object): def init(self): #Game初始化 # action是MOVE_STAY、MOVE_LEFT、MOVE_RIGHT # ai控制棒子左右移动;返回游戏界面像素数和对应的奖励。(像素->奖励->强化棒子往奖励高的方向移动) def step(self, action):# learning_rateLEARNING_RATE = 0.99# 跟新梯度INITIAL_EPSILON = 1.0FINAL_EPSILON = 0.05# 测试观测次数EXPLORE = 500000 OBSERVE = 500# 记忆经验大小REPLAY_MEMORY = 500000# 每次训练取出的记录数BATCH = 100# 输出层神经元数。代表3种操作-MOVE_STAY:[1, 0, 0] MOVE_LEFT:[0, 1, 0] MOVE_RIGHT:[0, 0, 1] output = 3 # MOVE_STAY:[1, 0, 0] MOVE_LEFT:[0, 1, 0] MOVE_RIGHT:[0, 0, 1]input_image = tf.placeholder(“float”, [None, 80, 100, 4]) # 游戏像素action = tf.placeholder(“float”, [None, output]) # 操作#定义CNN-卷积神经网络def convolutional_neural_network(input_image): weights = {‘w_conv1’:tf.Variable(tf.zeros([8, 8, 4, 32])), ‘w_conv2’:tf.Variable(tf.zeros([4, 4, 32, 64])), ‘w_conv3’:tf.Variable(tf.zeros([3, 3, 64, 64])), ‘w_fc4’:tf.Variable(tf.zeros([3456, 784])), ‘w_out’:tf.Variable(tf.zeros([784, output]))} biases = {‘b_conv1’:tf.Variable(tf.zeros([32])), ‘b_conv2’:tf.Variable(tf.zeros([64])), ‘b_conv3’:tf.Variable(tf.zeros([64])), ‘b_fc4’:tf.Variable(tf.zeros([784])), ‘b_out’:tf.Variable(tf.zeros([output]))} conv1 = tf.nn.relu(tf.nn.conv2d(input_image, weights[‘w_conv1’], strides = [1, 4, 4, 1], padding = “VALID”) + biases[‘b_conv1’]) conv2 = tf.nn.relu(tf.nn.conv2d(conv1, weights[‘w_conv2’], strides = [1, 2, 2, 1], padding = “VALID”) + biases[‘b_conv2’]) conv3 = tf.nn.relu(tf.nn.conv2d(conv2, weights[‘w_conv3’], strides = [1, 1, 1, 1], padding = “VALID”) + biases[‘b_conv3’]) conv3_flat = tf.reshape(conv3, [-1, 3456]) fc4 = tf.nn.relu(tf.matmul(conv3_flat, weights[‘w_fc4’]) + biases[‘b_fc4’]) output_layer = tf.matmul(fc4, weights[‘w_out’]) + biases[‘b_out’] return output_layer#训练神经网络def train_neural_network(input_image): predict_action = convolutional_neural_network(input_image) argmax = tf.placeholder(“float”, [None, output]) gt = tf.placeholder(“float”, [None]) action = tf.reduce_sum(tf.mul(predict_action, argmax), reduction_indices = 1) cost = tf.reduce_mean(tf.square(action - gt)) optimizer = tf.train.AdamOptimizer(1e-6).minimize(cost) game = Game() D = deque() _, image = game.step(MOVE_STAY) image = cv2.cvtColor(cv2.resize(image, (100, 80)), cv2.COLOR_BGR2GRAY) ret, image = cv2.threshold(image, 1, 255, cv2.THRESH_BINARY) input_image_data = np.stack((image, image, image, image), axis = 2) #print (“IMG2:%s” %input_image_data) with tf.Session() as sess: sess.run(tf.initialize_all_variables()) saver = tf.train.Saver() n = 0 epsilon = INITIAL_EPSILON while True: #print(“InputImageData:”, input_image_data) action_t = predict_action.eval(feed_dict = {input_image : [input_image_data]})[0] argmax_t = np.zeros([output], dtype=np.int) if(random.random() <= INITIAL_EPSILON): maxIndex = random.randrange(output) else: maxIndex = np.argmax(action_t) argmax_t[maxIndex] = 1 if epsilon > FINAL_EPSILON: epsilon -= (INITIAL_EPSILON - FINAL_EPSILON) / EXPLORE reward, image = game.step(list(argmax_t)) image = cv2.cvtColor(cv2.resize(image, (100, 80)), cv2.COLOR_BGR2GRAY) ret, image = cv2.threshold(image, 1, 255, cv2.THRESH_BINARY) image = np.reshape(image, (80, 100, 1)) input_image_data1 = np.append(image, input_image_data[:, :, 0:3], axis = 2) D.append((input_image_data, argmax_t, reward, input_image_data1)) if len(D) > REPLAY_MEMORY: D.popleft() if n > OBSERVE: minibatch = random.sample(D, BATCH) input_image_data_batch = [d[0] for d in minibatch] argmax_batch = [d[1] for d in minibatch] reward_batch = [d[2] for d in minibatch] input_image_data1_batch = [d[3] for d in minibatch] gt_batch = [] out_batch = predict_action.eval(feed_dict = {input_image : input_image_data1_batch}) for i in range(0, len(minibatch)): gt_batch.append(reward_batch[i] + LEARNING_RATE * np.max(out_batch[i])) print(“gt_batch:”, gt_batch, “argmax:”, argmax_batch) optimizer.run(feed_dict = {gt : gt_batch, argmax : argmax_batch, input_image : input_image_data_batch}) input_image_data = input_image_data1 n = n+1 print(n, “epsilon:”, epsilon, " " ,“action:”, maxIndex, " " ,“reward:”, reward)train_neural_network(input_image)6. 总结说到这里,相信你已经能对强化学习有了一个大致的了解。接下来的事情,应该是如何把这项技术应用到我们的工作中,让它发挥出应有的价值。问答什么时候使用某种强化学习算法?相关阅读使用 Q-Learning 实现 FlappyBird AI强化学习总结一文学习基于蒙特卡罗的强化学习方法 【每日课程推荐】机器学习实战!快速入门在线广告业务及CTR相应知识 ...

September 20, 2018 · 3 min · jiezi

原来你是这样的http2......

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~本文由mariolu发表于云+社区专栏序言目前HTTP/2.0(简称h2)已经在广泛使用(截止2018年8月根据Alexa流行度排名的头部1千万网站中,h2占比约29%,https://w3techs.com/technolog…)。写此文章的目的是:h2作为较新的技术,并逐渐占有率广泛,虽然目前有更新的QUIC,但其实现思路类似于h2。颠覆以往的HTTP/1.x,H2的创造性的技术值得我们细细品味。此篇文章根据笔者在h2开发经验和思考,向你介绍全面的h2知识以及是非功过。本篇更注重于帮助读者理解h2的设计思路、亦可作为一篇RFC导读或者总结。第一话、追踪溯源图1、HTTP年鉴图早在1991年,伴随WWW诞生之初,HTTP/0.9协议已经提出。HTTP0.9是简单且应用受限的协议。支持去网络主机获取对应路径的资源。但是没有扩展属性。其协议之简单甚至只用下面一个访问谷歌主机的例子概括了HTTP/0.9的全部。如下所示,协议只支持GET,没有http头;响应只能是超文本。telnet google.com 80Connected to x.x.x.xGET /about(Hyper text)(Conection closed)随着人们对富媒体信息的渴望以及浏览器的普及,HTTP/1.0在1996年被提出来。HTTP/1.0的很多特性目前还被广泛使用,但是仍然像HTTP/0.9一样一次请求需要创建一次的tcp连接。随即短短几年时间内,HTTP/1.1以RFC标准形式再次展现在人们眼前。此时的HTTP协议1.1版本已经重新设计了长连接、options请求方法、cache头、upgrade头、range头、transfer-encoding头, 以及pieline(in order)等概念。而我们另一个所熟知的HTTPS的SSL/TLS技术各个版本差不多在后来的十年间逐渐被提出。出于安全考虑,互联网通信间的防火墙路由交换机等设备,这些设备一般仅会开发有限的端口(如80和443)。各种版本的通信协议只能复用这些端口。HTTP1.1的80端口设计了upgrade请求头升级到更高级的协议,而443端口为了避免多消耗个网络RTT,在tls握手过程中使用了NPN/ALPN技术直接在通信之前保持CS两端的协议一致。NPN/ALPN是是TLS协议扩展,其中NPN是Google为实现spdy提出的。由服务端提供可支持的协议,供客户端选择。ALPN则是更接近于HTTP交互的方式,由客户端先发出使用某种协议的请求,由服务端确认是否支持协议。ALPN为了HTTP2诞生做铺垫。另外一个不得不提的是spdy协议。Spdy旨在解决HTTP1.1的线头阻塞问题(后面章节有详细讨论)于2009被google提出。同时分别于2012提出了spdy3.0实现了流控制,2013-2014期间提出了流优先级,server push等概念。Spdy的存在意义更像是http2.0的体验服。它为探索HTTP继续演进道路做了铺垫。第二话、人机交互汇编是效率最高的语言之一,但是又是最晦涩难懂的语言之一。而人脑易懂的编程语言往往牺牲性能作为折衷。简单说,HTTP/1.x协议就是为了人类语言习惯所设计的协议,但是转换成机器执行协议并不是高效的。让我们在回顾下计算机执行解析HTTP1.x的流程。GET / HTTP/1.1<crlf>Host: xxx.aa.com<crlf><crlf>对应的解析伪代码是loop while(! CRLF) read bytes end while if line 1: parse line as Request-Line else if empty line: Break out and We have done else If start with non-whitespace parse header else if space continue with last heade end ifend loop在伪代码解析流程可以看到,肉眼看起来简洁的协议解析起来是这么的费劲。而且在HTTP服务器中还要考虑这种问题:字节行的长度是未知的,也不知道预先分配多大内存。HTTP/2.0使用了计算机易懂的二进制编码信息,而且得向上兼容HTTP的涵义。具体我们来看下他是如何做到的。像大多数通信协议一样,桢是传输最小单位。桢分为数据帧和控制桢。数据帧作为数据的载体,控制桢控制信道的信令。h2桢的通用格式为首部9字节+额外的字符。正如你能想到的那样,桢的第一个部分是描述长度,第二个部分描述了桢的类型,第三个部分描述了标志Flag,第四个部分是唯一序列号。这是所有桢的通用头。通用头紧接的是桢的实体。图4展示了桢的结构。图2、通用桢的格式这样设计有什么好处呢。再来看一下桢的解析流程,你就会发现对计算机来说更简洁。loop read 9 byte payload_Length=first 3 bytes read payload swith type: Take actionend loopHTTP2.0使用header桢表达HTTP header+request line,data桢表达Body。header桢和data桢使用相同的stream id组成一个完整的HTTP请求/响应包。这里的stream描述了一次请求和响应,相当于完成了一次HTTP/1.x的短连接请求和响应。第三话、并行不悖上节讲到我们用h2桢完整表达了HTTP/1.x。但是h2协议抱负远不止于此。它的真正目的是解决之前HTTP1.x的线头阻塞问题、改善网络延迟和页面加载时间。我们知道一个完整的网页包含了主页请求和数次或数十次的子请求。HTTP/1.1已经可以并行发出所有请求.但是HTTP本身是无状态的协议,它依赖于时间的顺序来识别请求和响应直接的对应关系。先来的请求必须先给响应。那么如果后面的响应资源对浏览器构建DOM或者CSSOM更重要。那它必须阻塞等待前者完成。当然这也难不倒我们,我们可以多开几条tcp连接(浏览器规定一个origin(协议+host+port)最多6个)或者合并资源来减少不必要的阻塞。这是有代价的。首先tcp建连的开销,其实合并资源带来一小块子资源过期导致整个合并资源的缓存过期。对此,h2有一揽子的解决方案,接下来一一道来。h2在一个tcp连接创建多个流。每个流可以有从属关系,比如说根据浏览器加载的优先级顺序(主请求>CSS>能改变DOM结构的JS文件>图片和字体资源文件)建立一条依赖关系链。处于同一等级的依赖关系中可以设置权重。权重用于分配传输信道资源多少。图6例子说明了有一次主页请求index.html、一次main.css,一次jq.js以及一些image文件和字体文件qq.tff图3、h2请求的依赖树HTML的优先级最高,在HTML传输完成之前,其他文件不会被传输。HTML传输完成后,JS和CSS根据其分配的权重占比分配信息传输资源。如果CSS传输完成后,TFF和PNG如果是相同权重,那么他们将占有1/4的信道资源。这里抛出3个问题和答案。如果CSS被阻塞了,那么 JS 得到本属于CSS的通信资源如果CSS传输完成但没有被移依赖树, TFF和PNG继承CSS的通信份额 (假设TFF和PNG权重一样,那么各分得1/4通信资源).如果CSS在依赖数被移除,JS, TFF, PNG平分通信资源(假设3个权重一样,那么三者各分得1/3通信资源)第四话、众星捧月HTTP2还设计了一系列方案来改善网络的性能、包括流量控制,HPack压缩,Server Push。什么你说TCP已经有流量控制了,HTTP不是多此一举吗?没错,但是在单条TCP内部,各个流可是没有流量控制。流量控制使用了Update Frame不断告知发送方更新发送的窗口大小(上限)。流量控制一个现实用途是阻塞不重要的请求,以腾出更大的通信资源给重要的请求使用。流量控制是不可以被关闭的,流量大小可以设置2的31次方-1(2GB)。不同的中间网络设备有不一样的吞吐能力。流控的另一个用途在于同步所有的中间设备交换机最小的上限。流量窗口初始大小为65535(2的16次方-1)。就像世界上的大多数财富聚集在少数人身上一样。在一份对48,452,989个请求的统计中,以下11个头占据了99%的数量,依名次递减分别是user-agent、accetp-encoding、accept-language、accept、referer、host、connection、cookie、origin、upgrade-inseure-request、content-type。http header的值也有很大相似性,比如说”/index.html“, “gzip, deflate”。Cookie也携带冗余的信息。这些都组成了http header大量可以压缩的内容。而在一份GET请求和一个304响应或者content-length很少的响应中,这些头占据了很大比例的通信资源。2016年发布的一份HTTP报告中,请求头大约在460bytes,对一个通常的网页,平均会有140个请求对象。这些头总共需要63KB。这些量很有可能会是首屏和页面加载时间优化的瓶颈。可能你会说用gzip等压缩算法这些请求头,不就完了吗?的确spdy就这样干过,直到2013年BREACH攻击暴露了gzip压缩在https应用的安全性,这种攻击让攻击者很容易获得session cookie等数据。于是才有了HPACK。HPACK简单来说就是索引表,包括静态表和动态表。静态表由RFC定义,从不改变,静态表预留了62个表项。每个连接的通信双方维护着动态表。H2协议使用索引号代表http中的name、value或者name-value。假设被索引的是name,value没有索引,那么value还可以用霍夫曼编码压缩。在预定的头字段静态映射表 中已经有预定义的 Header Name 和 Header Value值,这时候的二进制数据格式如图4, 第一位固定为1, 后面7位为映射的索引值。图8的83就是这样的,83的二进制字节标示1000 0011,抹掉首位就是 3 , 对应的静态映射表中的method:POST。图4、index索引name和value图5、抓包示意预定的头字段静态映射表中有 name,需要设置新值。图6所示例子,一个指定 path的Header,首字符 为 44 ,对应的二进制位0100 0100。前两个字符为 01 ,Index 为 4 ,即对应静态映射表中的 path 头。第二个字符为 95对应的二进制位 1001 0101,排除首字符对应的 Value Length 为 十进制的21。即 算上 44,一共23个字符来记录这个信息。图6、index索引name和自定义value图7、抓包示意预定的头字段静态映射表中没有 name,需要设置新name和新值。40 的二进制是0100 0000,02 的二进制是0000 0010,后七位的十进制值是 2,86 的二进制是1000 0110,后7位的十进制值是6。图8、index索引自定义name和自定义value图9、抓包示意明确要求该请求头不做hpack的indexHTTP2.0还有个大杀器是Server Push,Server Push利用闲置的带宽资源可以向浏览器预推送页面展示的关键资源,Server push有效得降低了页面加载时间。具体详情参考笔者的另一篇文章https://cloud.tencent.com/dev…。第五话、庖丁解牛HTTP2相比HTTP1更适合计算机执行。但是其二进制特性不易于人脑理解。这一话我们专门来讲讲关于http2的调试工具。Chrome(qq浏览器)可以按住F12查看h2协议。图13所示为浏览器网络时序图,列出了具体协议名称。chrome还可以在地址栏敲入chrome://net-internals/#http2查看到h2协议细节,如图11所示。点击相应的host就可以看到h2协商过程,如图12所示。图10、浏览器的网络时序图chrome://net-internals/#http2图11、chrome调试h2图12、h2协商过程wireshark(需和chrome或firefox搭配使用)。设置环境变量SSLKEYLOGFILE=c:tempsslkeylog.log。然后在Wireshark->Preferences->Protocols->SSL配置key所在路径。图13、wireshark配置图14、wireshark抓h2包Nghttp2是一个完整的http2协议实现的组件。作者也参与过spdy实现。目前nghttp2库被很多知名软件作为h2协议实现库使用。另外nghttp2也自带了h2协议的分析工具。图18展示了在明文状态使用upgrade头升级到h2c。图19展示了在https基础上升级到h2。图15、明文状态使用upgrade头升级到h2c图16、展示了在https基础上升级到h2Curl的—http2选项(需要和nghttp2一起编译)图17、支持h2的curl客户端调试Github还有些实用的http2工具组件,诸如chrome-http2-log-parser、http2-push-manifest等组件,笔者后续会专门开篇文章介绍这些工具。对于移动端的调试,ios可以用charles proxy做代理,android需要开发者模式使用移动端的chrome,笔者在移动端使用较少,这里就不做展开。第六话、雕栏玉砌H2怎么部署呢,目前主流服务端像nginx、apache都已经支持http2,主流的客户端curl和各种浏览器(包括移动端safari和chrome-android)基本也支持http2。代理服务器如ATS、Varnish,Akamai、腾讯云等CDN服务也支持http2。那么怎么把一套网站部署到h2。或者说部署h2网站和之前h1网站有什么不一样?如果是自己的源站,那么请确保服务器支持TLS1.2已经RFC7540所要求的加密套件,h2需要保证支持alpn。你可以使用ssllabs等网站检查。对于h2服务器的要求是h2必须了解如何设置流的优先级,h2服务器需要支持server push。h2客户端需要尽量多的发送请求。如果你的网站是从http1.x迁移过来的,那么之前对于http1.x所做的优化可能无任何帮助甚至更差。合并小文件不在需要,因为额外的小文件请求在h2看来只是开销很少。并且如果大文件的局部更改使得整个大文件缓存失效。在http1.0时代使用多个域名来并发http连接,在http2也毫无必要,因为http2天生就是并发的。http1.x做的优化比如说图片资源文件不使用cookie来减少请求大小,http2的header压缩功能也减少了这种影响。即使不做这种优化也亦可。像合并css、小图片带来的增益在http2.0也是可忽略的。如果网页使用第三方网站组件,那么请尽可能减少使用第三方网站组件。第三方网站不能保证支持h2,所以它可能成为木桶理论的最大短板。谨慎使用2.0-1.x的部署方案,h2流转化成h1请求。因为这样无法发挥h2性能。图18、2.0-1.x的部署方案CDN代理服务器的h2支持,可以屏蔽h2强制走tls的代理服务器。如图19,代理可以在与各种协议客户端的网络环境下,切断和客户端的tls连接,和服务器新建连接。也可以作为load balancer,相当于HTTP2.0用户和HTTP2.x服务器直接通信。图19、带tls客户端功能的代理图20列举如果绕过proxy到达h2服务器。此时的proxy相当于tcp转发的load balance功能的设备。如果该proxy支持tls的alpn协议,那么它也可以选择HTTP代理功能,和h2服务器可以建立加密连接。如果即不支持alpn,也不支持tcp转发。那么proxy只能用upgrade升级成h2协议。图20、经过代理服务器的H2部署方案第七话、十全九美HTTP2.0是建立在TCP之上,所以TCP的所有缺点他都有,所以H2能发挥最大性能得益于调优的tcp协议栈。TCP的慢启动特性,决定h2一开始的并发流量不会太大,TCP以及SSL的握手连接也会拖慢h2的首包网络耗时。QUIC则完全地抛弃TCP,在UDP基础上实现了HTTP2的一系列特性。同时做了应用层的如TCP的可靠性保障。同时这些TLS1.3传输更快更简洁。这些都为HTTP2.0进化到HTTP3.0提供了一些思路。总结以上内容都来源于笔者的实践经验和理论总结。篇幅所限不能涵盖各个细节。具体可以继续参考RFC7540和RFC7541协议。问答没有“http | https”的网址怎么实现?相关阅读我是怎么一步步用go找出压测性能瓶颈HTTP/2之服务器推送(Server Push)最佳实践低于0.01%的极致Crash率是怎么做到的? 【每日课程推荐】新加坡南洋理工大学博士,带你深度学习NLP技术 ...

September 5, 2018 · 1 min · jiezi