源自于我做的一次公司内部的技术分享,这是初稿。 PPT 就不贴了。

一. 序章: 可计算模型

1936 阿隆佐·邱奇发表可计算函数的第一份精确定义,即Lambda演算(λ演算)。λ演算是一套从数学逻辑中发展,以变量绑定和替换的规则,来研究函数如何抽象化定义、函数如何被应用以及递归的形式系统。
1936 艾伦·图灵提出图灵机设想,通过TAPE,HEAD,TABLE,STATE四个部分模拟人的纸笔运算
1945 冯·诺伊曼提出冯·诺伊曼结构(存储程序型电脑),是通用图灵机实现
1958 约翰·麦卡锡,发明了一种列表处理语言(Lisp),这种语言是一种阿隆佐lambda演算在现实世界的实现,而且它能在冯·诺伊曼计算机上运行

图灵机设想和 Lamdba 演算都是一种抽象计算模型,是解决可计算问题的一种方案,通俗来讲,就是将计算以数学的方式抽象化,以便证明和推导。图灵机和 Lamdba 演算这两个可计算理论已经被证明是等价的。

阅读全文 »

一. pprof 数据采样

pprof 采样数据主要有三种获取方式:

  • runtime/pprof: 手动调用runtime.StartCPUProfile或者runtime.StopCPUProfile等 API来生成和写入采样文件,灵活性高
  • net/http/pprof: 通过 http 服务获取Profile采样文件,简单易用,适用于对应用程序的整体监控。通过 runtime/pprof 实现
  • go test: 通过 go test -bench . -cpuprofile prof.cpu生成采样文件 适用对函数进行针对性测试
阅读全文 »

一. 容器资源限制

Docker资源限制主要靠Linux cgroups技术实现,简单说,cgroups是一个个的进程组(实际上是进程树),这些进程树通过挂接 subsystem(事实上是挂接到 cgroup 上层的hierarchy)来实现对各种资源的限制和追踪,subsystem是内核附加在程序上的一系列钩子(hooks),通过程序运行时对资源的调度触发相应的钩子以达到资源追踪和限制的目的。cgroups 技术的具体介绍和实现参考文末链接。

阅读全文 »

一. Docker Machine

通常我们使用的Docker都是直接在物理机上安装Docker Engine,docker-machine是一个在虚拟机上安装Docker Engine的工具,使用起来很方便:

# 创建一个docker machine,命名为abc
> docker-machine create abc
# 列出当前主机上所有的docker machine
> docker-machine ls
# 通过ssh连接到abc
> docker-machine ssh abc
# 现在就已经在abc machine上,可以像使用Docker Engine一样正常使用
docker@abc:~$ docker ps
# 退出machine
docker@abc:~$ exit

docker-machine可以用来在本机部署Docker集群,或者在云上部署Docker。docker-machine支持多种虚拟方案,virtualbox,xhyve,hyperv等等。具体使用比较简单,命令参考附录文档。

阅读全文 »

Go基于CSP模型,提倡”Share memory by communicating; don’t communicate by sharing memory.”,亦即通过channel来实现goroutine之间的数据共享,但很多时候用锁仍然是不可避免的,它可以让流程更直观明了,并且减少内存占用等。通常我们的实践是用channel传递数据的所有权,分配工作和同步异步结果等,而用锁来共享状态和配置等信息。

本文从偏实现的角度学习下Go的atomic.Load/Store,atomic.Value,以及sync.Map。

阅读全文 »

本文从源码的角度学习下Go接口的底层实现,以及接口赋值,反射,断言的实现原理。作为对比,用到了go1.8.6和go1.9.1两个版本。

1. eface

空接口通过eface结构体实现,位于runtime/runtime2.go:

阅读全文 »

G P M 模型

定义于src/runtime/runtime2.go:

  • G: Gourtines, 每个Goroutine对应一个G结构体,G保存Goroutine的运行堆栈,即并发任务状态。G并非执行体,每个G需要绑定到P才能被调度执行。
  • P: Processors, 对G来说,P相当于CPU核,G只有绑定到P(在P的local runq中)才能被调度。对M来说,P提供了相关的执行环境(Context),如内存分配状态(mcache),任务队列(G)等
  • M: Machine, OS线程抽象,负责调度任务,和某个P绑定,从P的runq中不断取出G,切换堆栈并执行,M本身不具备执行状态,在需要任务切换时,M将堆栈状态写回G,任何其它M都能据此恢复执行。
阅读全文 »

本文是Coursera课程Neural Networks and Deep Learning的学习笔记,课程本身深入浅出,质量非常高,这里主要做思路整理和知识备忘,很多模块还需要自己扩展。

什么是深度学习(Deep Learning)?简单来说,深度学习是机器学习的一个子领域,研究受人工神经网络的大脑的结构和功能启发而创造的算法。Wiki上给出的解释则更复杂一点: 深度学习(deep learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。

一. 逻辑回归模型

监督学习(Supervised learning): 是一个机器学习中的方法,可以由训练资料中学到或建立一个模式(函数 / learning model),并依此模式推测新的实例。训练资料是由输入物件(通常表示为张量)和预期输出(Label标签层)所组成。函数的输出可以是一个连续的值(称为回归分析),或是预测一个分类标签(称作分类)。

逻辑回归算法

逻辑回归算法是一个分类算法,通常用在二元分类中(也可以通过一对多策略实现多类别逻辑回归,用于多元分类),用于估计某种(或多种)事物的可能性,是监督学习的常用算法之一。假设我们要设计一个算法识别某张图片是不是一只猫,逻辑回归算法会输出该图片是猫的概率(由于概率是0-1连续的,因此逻辑回归中有回归二字,但它最终是为了解决分类问题的)。我们可以将图片的RGB通道放入到一个输入向量中,比如图片大小为100*100,则最终得到长度为3*100*100的输入向量x,即x(n)=30000(每张图片的特征维度)。逻辑回归算法对于每个输入向量$x^i$,都应该计算得到对应的预估值$y^i$([0,1])。现在来看看如何设计这个算法,最简单的函数是: ,其中w为维度为n的列向量,我们用$ \hat{y} $来表示算法得到的预估值,以和训练数据中的已知结果$y$区分,这是典型的线性回归函数(将多维特征映射为单个线性连续值),在该函数中,$y$取值为负无穷到正无穷,而我们期望的$y$取值为[0,1]。因此我们还需要进行一次转换,一个经典的非线性转换函数是sigmoid函数 $y = \sigma(z) = \frac{1}{(1+e^{-z})}$,其中 $z = w.T*x + b$,这样我们的到$y$值始终限定在0($z$无穷小时)到1($z$无穷大时)之间。现在我们有了一个最简单的逻辑回归算法模型,接下来的任务就是根据训练集的特征和标签,得到最佳的$w$和$b$参数,使得该算法在测试集上的预测准确率变高。

阅读全文 »

先来看看GC(自动垃圾回收)的主要问题:

  1. 额外的开销(内存/CPU)
  2. 执行GC的时机无法预测,在实时性要求高的场景或事务处理来说可能是不可容忍的
  3. 部分GC算法会Stop-the-world

各语言运行时在选取GC算法时,都要从这几个方面进行衡量与取舍,下面是一些常见的GC算法。

阅读全文 »

最近有在博客中嵌入公式的需求,目前主要有两个数学公式渲染引擎mathjax和KaTeX,前者应用更广泛,支持的语法更全面,因此这里简述将mathjax整合到hexo。

1. 替换Markdown渲染器

npm uninstall hexo-renderer-marked --save
npm install hexo-renderer-kramed --save

hexo-renderer-karmed渲染器fork自hexo-renderer-marked,对mathjax的支持更友好,特别是下划线处理(marked会优先将_之间的内容斜体转义)

2. 挂载mathjax脚本

在主题layout/_partial/目录下添加mathjax.ejs:

阅读全文 »