ACM Professional Membership

题外话 为什么深度学习有这么强大的功能,这背后我们可以想到人类的大脑神经元,单个神经元不能起到任何作用,但是一堆神经元在一起的力量是无穷的。 观看一部关于生命体中细胞和蛋白质都是怎么运作的,我们会非常惊讶为什么小小的微观世界会以如此精妙的方式运作。 Inner Life Of A Cell - Full Version 有时候想到上面的问题,自己就有点冲动,想去了解更多关于这个世界是如何运作的知识,人与人之间的沟通交流是否可以类比成分子间的相互作用,为什么一堆神经元组成在一起就可以造就智慧的生命体,这种生命体的自由意识是如何形成的,神经元之间的信息传递是如何编码的,在深度学习领域是否还能继续利用大脑神经元的某些特点来增强模型的设计。 为了解开这些困惑的问题,开阔自己的见识,我买了四本重要的外文书籍。 关于引力理论的探索 有关基因与遗传方面的介绍 神经理论科学 分子机器理论 这里的每一本书或许都可以帮助我们在深度学习领域里走得更远。 最低价格看Oreilly动物书 因为工作原因需要购买programming Kubernetes这本书,我在国内找了好几家线上书店,价格都非常贵,基本上一本就要600RMB,自己又不想使用盗版书籍,所以就想办法能不能通过第三方渠道低价格去看这些技术书,于是就有了下面的解决方案。 购买途径 注册ACM会员,ACM全称是Association For Computing Machinery 国际计算机协会,进入发展中国家会员注册,在国家里面选择中国,然后按照流程注册即可,最后支付年费就可以了。 目前的费用表单: 如果只是为单纯的获取电子刊物信息,可以选择最基本的170RMB。 注册完成之后我们就可以进入动物园看书了。 访问ACM Learning Center 点击右上角的O’Reilly就可以登入到O’Reilly上在线查看和学习各种新技术的书籍,因为新技术一直会更新迭代,如果纯粹是为了学习一门新技术,那么还是建议购买电子书,外文纸质书一般都比较贵,省下的钱可以考虑买经典的纸质书,就像我上面列举的那四本,经典的永远不会过时。

September 9, 2020

History of Kubernets

Kubernets Wiki 最近看了Large-scale cluster management at Google with Borg,Borg是谷歌公司自己内部开发的一套集群管理系统,后来开源社区也就慢慢开始孵化和推出了Kubernets集群管理系统,k8s和Borg有着很深的渊源关系。 先从Kubernets入手,我们来看下K8s的组件: Kubelet 在每一台节点上都会运行Kubelet,管理节点上的容器。 kube-apiServer 验证和配置关于Pods,Services,ReplicationControllers等数据,其他kube都需要通过调用api来获取所需的数据。 kube-Controller-Manager 用于控制系统的状态,通过API接口来同步系统数据,比如将系统从A状态同步更新到B状态。 kube-proxy 运行在每一台的节点上,主要作用充当网络代理,能够简单的处理TCP UDP 转发和轮询。 kube-scheduler 用来调度Pods,当有新的Pods需要创建时,调度器会给每一台工作节点打分,然后将Pods分配到满足要求的节点上。 然后再看关于Borg系统的描述,每一个集群都称之为一个Cell,每一个Cell都运行在一个独立的数据中心里。 Borg 架构 Borg 设计准则主要是以下三点: 隐藏对系统底层资源的管理以及容错处理,方便开发者将注意力集中在开发上,而不过多注意底层细节。 系统中运行的应用都是高可用的,某台节点的宕机,不会引起服务的不可用。 必须非常高效的在数万台节点上完成对应用的扩展。 Borg的用户基本上是google内部开发人员和SRE,正是因为google注重对SRE的发展,才慢慢在google内部形成了上述三点的认知体系,提到google SRE不得不提GOOGLE SRE How Google Runs Production Systems这本书,我只看过中文版,看完英文版之后会写一篇博客专门详细讨论这本书里的内容。 集群设计架构 Borg系统有一套自己的配置文件语法体系BCL,然后通过borgcfg加载到基于Paxos的分布式数据库存储中,在k8s中我们是通过编写Yaml状态配置文件,然后使用kubectl将状态配置通过kube-api接口提交到后端分布式ETCD存储中,在边缘设施的k8s场景中,像k3s,microk8s会默认使用基于SQL的数据库引擎Dqlite,dqlite也采用了Raft一致性存储协议,这样就可以做到边缘设备上的k8s高可用。 在Borg系统中,SRE工程师大部分通过Borgctl命令行工具对系统进行访问和修改。 Borg的核心组成部分有Scheduler,BorgMaster,Paxos Datastore,LinkShard,Borglet。 BorgMaster: master分为两部分,第一部分是对外处理请求,比如RPC调用获取集群状态,任务分配信息,获取borglet的状态,第二部分是用于处理集群内部的任务调度模块,master 支持高可用,所有的数据都是通过基于Paxos的数据库进行存储,当前master leader宕机之后,master 副本中会选举出新的master节点继续对外提供服务。最引人注目的是,master节点的数据存储使用了CheckPoint技术,每隔一段时间,系统都会自动保存当前的状态到checkpoint中,这样在集群发生问题的时候,我们就能将集群回退到前一个正常的checkpoint的状态,并且在线下使用这些point来做debug。 BorgScheduler: 当任务通过master提交之后,master会将数据存储到paxos中,并且将任务放到待处理队列中,Scheduler会根据这些任务的优先级进行先后处理,Scheduler拿到任务之后,计算哪些机器是符合要求的,根据一定的打分算法给这些机器打分,再根据分数将任务分配到对应的节点上。 Borglet: 运行在每一台节点上,用于管理任务的生命周期,比如停止运行重启,维护操作系统的内核配置,borgmaster会定期去拉取let上的状态信息,如果let没有应答那么master就认为这个对应节点已经下线或者宕机。 Jobs&&Tasks: Borgs运行的对象以Jobs Tasks来进行管理,一个Job可以由多个Tasks组成。以下是任务的生命周期。 当任务被提交到Borg Master时,如果任务被master接受则会进入Pending状态,等待Scheduler进行调度,调度完成之后,组成job’s Tasks就开始运行,如果超出系统的资源限制,Tasks就会被Evicted,然后进入Pending状态,继续等待被调度到新的节点上,当Tasks运行结束,任务的状态会被更新为Dead,有点像进程的生命周期,整个主干过程就是 Create -> Pending -> Scheduling -> Runing -> Dead。 然后我们看下k8s整个架构以及任务的调度是如何完成的,可以与Borg对比,发现两者的优缺点。 ...

September 7, 2020

Run Mathematica armhf on RaspberryPi aarch64

Why 使用Mathematica + Python web framework提供对外的服务平台,由于机器上运行的都是AARCH64系统,而ARM Mathematica目前只支持32位的v6 v7,需要在aarch64上增加支持armhf v6 v7的运行时库。 Small TIPS 为了能够在Ubuntu 20.04 aarch64 系统上运行Mathematica ARM 32Bit,查阅了很多相关资料,最后试验成功,可以通过以下方式在aarch64系统上运行32位的Mathematica。 最主要的就是这一行:dpkg –add-architecture armhf 添加armhf源,后面就是安装对应的armhf libc libc++ zlib。 Mathematica 的相关程式安装包在这里 FROM ubuntu:20.04 RUN apt-get update RUN dpkg --add-architecture armhf RUN apt-get update RUN apt-get install libc6-dev:armhf libstdc++-9-dev:armhf zlib1g-dev:armhf COPY ./ /tmp/ WORKDIR /tmp RUN apt install ./wolframscript_1.4.0+2020081702_armhf.deb -y RUN apt install ./wolfram-engine_12.1.1+2020081901_armhf -y WORKDIR / Python Web and Wolfram Backend Demo 对应于Mathematica armhf位版本,安装gcc和g++都为armhf版本,所以我们安装的Python和Python Modules也需要对应到armhf。 ...

August 25, 2020

Mathematica Json 解析

今天在工作过程中遇到需要解析JSON文件,得到其中的一个关键字,准备用Mathematica练练手,文件如下,需要解析"pubkey"这个字段。 { "apiVersion": "v1", "data": { "voting-keystore.json": "{\"version\": 4, \"pubkey\": \"a94300da6d73a11d8ba72c99dd385b7a9d5043c9ee83ffd4190d89b7677e68d384fbceb556d2a0652e81250ad4b8477d\", \"uuid\": \"09e5c322-bf6b-401a-b90d-1aef6d57996a\", \"crypto\": {\"checksum\": {\"message\": \"704e947d244bc8020ef6d6f0844c4aea08af18ecf345bb98ab999df6441377d7\", \"function\": \"sha256\", \"params\": {}}, \"kdf\": {\"message\": \"\", \"function\": \"scrypt\", \"params\": {\"p\": 1, \"n\": 32768, \"salt\": \"b891518a06f1d3f67a6d485bba8627f5320497f98c08cb52e4391e50071ac97d\", \"dklen\": 32, \"r\": 8}}, \"cipher\": {\"message\": \"bcd85ce03e82e645e13501f717d907c03a23ee1f8dc6bd045c53001719ddc7a5\", \"function\": \"aes-128-ctr\", \"params\": {\"iv\": \"7f05ffce95bcd0157e520c6b949b90b1\"}}}, \"path\": \"\"}" }, "kind": "ConfigMap", "metadata": { "creationTimestamp": "2020-07-25T11:35:24Z", "managedFields": [ { "apiVersion": "v1", "fieldsType": "FieldsV1", "fieldsV1": { "f:data": { ".": {}, "f:voting-keystore.json": {} } }, "manager": "Swagger-Codegen", "operation": "Update", "time": "2020-07-25T11:35:24Z" } ], "name": "lighthouse-validator-a94300da6d73", "namespace": "eth", "resourceVersion": "1200502", "selfLink": "/api/v1/namespaces/eth/configmaps/lighthouse-validator-a94300da6d73", "uid": "05b37640-be81-4944-9c9f-868431b6107f" } } 使用wolfram语言一行搞定: ...

July 27, 2020

TF-MPI-分布式训练

Horovod 之前写过一篇文章讨论如何使用TF2.0自带的分布式训练系统,在树莓派4上建立分布式训练集群。然而这里会有一个缺陷,我们需要在每一个节点上去启动写好的训练程式,等全部启动之后,整个分布式训练才会开始运作,那么能否通过MPI消息传递接口来完成分布式的训练,答案就在Uber开发的Horovod,MPI主要用在超算领域,在树莓上搭建MPI集群,第一个可以用来学习超算上的分布式计算,第二可以在实际中观察TF在ARMv8上进行分布式训练的性能。 回顾 horovod的开发可以从研究这篇论文开始Horovod: fast and easy distributed deep learning in Tensorflow 一般常见的分布式并行处理有两种,一种是数据并行,一种是模型并行,这个在之前的文章中讨论过,数据并行的优势是相对简单的。 数据并行流程: 在每个节点上分发拷贝模型代码并运行 每个节点读取数据集开始训练 根据损失函数计算模型的梯度 合并每个节点所计算得到的梯度值,计算出新的平均梯度 根据计算得到的新梯度,更新每个节点上模型的参数和权重 重复上述过程 早期TF的分布式训练为PS架构,Worker训练模型,将获得的梯度发往parameter server,PS服务将收集到的数据进行均值化处理,开发人员需要在每台节点上启动Worker和PS,然后TF通过服务发现机制接入整个训练集群,这样就会出现两个瓶颈。 当只有一台PS服务时,会出现PS负载过高的情况 当有多台PS和多台Worker时,训练的瓶颈会出现在网络带宽层面 接下来就有了Ring-All-Reduce算法: 每个Worker节点连在一起形成闭环,通过以下算法将所有节点的梯度值的聚合存储在worker节点上: (->代表将数值传递到下一个worker节点,k代表数组号) 在MPI消息接口中,已经实现了AllReduce功能,MPICH MPI_Allreduce,程式中关于梯度的均值计算就只需要一个AllReduce()操作,然后再将得到的新梯度重新传递给每一个Worker。 使用horovod只需要在程式中增加horovod初始化和基于MPI的optimizer更新 论文中关于使用ring-allreduce和之前原版本TF性能利用率对比图: 以下所有分布式训练均可在树莓派4集群上完成。 训练MNIST LeNet代码如下: #!/bin/env python3 # -*- coding: utf-8 -*- """ Spyder Editor This is a temporary script file. """ import numpy as np import tensorflow as tf from tensorflow import keras import horovod.tensorflow.keras as hvd hvd.init() // horovod 初始化 mnist = keras.datasets.mnist (x_train, y_train), (x_test, y_test) = mnist.load_data() x_train, x_test = x_train / 255.0, x_test / 255.0 x_train,x_test = np.expand_dims(x_train, axis=3), np.expand_dims(x_test, axis=3) model = keras.models.Sequential([ keras.layers.Conv2D(32, 3, padding='same', activation='relu',input_shape=(28,28,1)), keras.layers.MaxPool2D(2), keras.layers.Conv2D(64, 3, padding='same',activation='relu'), keras.layers.MaxPool2D((2)), keras.layers.Flatten(), keras.layers.Dense(512, activation='relu'), keras.layers.Dense(10, activation='softmax')]) opt = tf.optimizers.Adam(0.001 * hvd.size()) opt = hvd.DistributedOptimizer(opt) // 增加分布式的优化器 model.compile(optimizer=opt,loss='sparse_categorical_crossentropy', metrics=['accuracy']) callbacks = [ hvd.callbacks.BroadcastGlobalVariablesCallback(0), ] if hvd.rank() == 0: callbacks.append(keras.callbacks.ModelCheckpoint('./checkpoint-{epoch}.h5')) model.fit(x_train, y_train,steps_per_epoch=500, callbacks=callbacks, epochs=20, verbose=1 if hvd.rank() == 0 else 0) MPICH 版本 构建镜像 Dockerfile ...

July 9, 2020

无线电领域的黑客工具 HackRFOne

July 2, 2020

Node-RED@Home

目标 继续接前一篇的NFS文件系统,目前的需求是需要能够控制集群中运行的应用,比如现在需要运行并行跨节点程序A,那么需要先调度停止正在运行的程序B,这就需要构建一个消息传递系统,能够基于消息驱动来完成操作任务。 前景和基本架构设计 Swift被设定为Tensorflow下一代的机器学习语言,参见Swift for Tensorflow,目前尝试着用Swift来编写应用。 使用MQTT协议来发送和接收需要处理的数据。 利用TinyML技术收集家用设备电器上传感器产生的数据,从而使得家电更加智能。 目前的设想是使用RabbitMQ做为消息中间件,Swift编写服务端应用推送消息,客户端需要一个UI应用接受和处理对应的消息事件,以下就是介绍一款基于消息驱动的可视化编程工具。 发现 Node-Red Node-Red是由IBM开发的基于流程的可视化编程工具。 个人觉得它的优点就是开发物联网应用原型速度快,支持Arduino,Raspberry Pi等设备,简单易用,基于事件驱动,原生开发语言为nodejs,支持可扩展插件。 运行在K3s上 node-red.yaml --- apiVersion: apps/v1 kind: Deployment metadata: name: node-red namespace: science labels: app: node-red spec: replicas: 1 selector: matchLabels: app: node-red template: metadata: labels: app: node-red spec: containers: - name: node-red image: $image imagePullPolicy: Always ports: - containerPort: 1880 volumeMounts: - mountPath: /data name: data-volume volumes: - name: data-volume persistentVolumeClaim: claimName: node-red-pvc --- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: node-red-pvc namespace: science annotations: volume.beta.kubernetes.io/storage-class: "managed-nfs-storage" spec: accessModes: - ReadWriteOnce resources: requests: storage: 6Gi --- apiVersion: v1 kind: Service metadata: name: node-red namespace: science spec: selector: app: node-red ports: - protocol: TCP port: 1880 targetPort: 1880 --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: node-red-ingress namespace: science spec: rules: - host: foo.bar.host http: paths: - backend: serviceName: node-red servicePort: 1880 Run RabbitMQ On K3s rabbitmq-conf-rabbitmq-env-configmap.yaml ...

June 29, 2020

Raspberry Pi K3s NFS FS

NFS on Raspberry Pi 目前正学习如何在树莓派4集群上结合gromacs+mpich的分子动力学模拟,所以需要搭建一款分布式存储系统,又由于树莓派性能的限制,搭建OpenEBS会比较浪费计算资源,最后就采用轻量级的NFS来完成文件系统的共享和存储。 NFS on K3s aarch64 基础依赖 NFS Server: sudo apt install nfs-kernel-server 添加共享文件目录到/etc/exports: /mnt/data/nfs 192.168.1.0/24(rw,sync,no_root_squash,no_subtree_check) # 外部使用 /mnt/data/kubedata 192.168.1.0/24(rw,sync,no_root_squash,no_subtree_check) # k3s 使用 启动 NFS Server: sudo systemctl restart nfs-kernel-server NFS Client: sudo apt install nfs-common sudo mount 192.168.1.145:/mnt/data/nfs ./nfs 添加到/etc/fstab: 192.168.1.145:/mnt/data/nfs /home/chenfeng/nfs nfs auto,nofail,noatime,nolock 0 0 K3s NFS Volume 需要使用Kubernets提供的NFS Client Provisioner k3s是跑在Ubuntu 20.04 aarch64 系统上的,而官方提供的NFS Client Provisioner是基于ARM v7的,所以需要重新编译Provisioner。 以下的操作全部在Raspberry pi 4上完成的。 以下为PATH: diff -ur ./Makefile /tmp/nfs-client/Makefile --- ./Makefile 2020-06-28 07:47:43.883181030 +0000 +++ /tmp/nfs-client/Makefile 2020-06-28 10:06:00.588586966 +0000 @@ -28,17 +28,16 @@ container: build image build_arm image_arm build: - CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-extldflags "-static"' -o docker/x86_64/nfs-client-provisioner ./cmd/nfs-client-provisioner + go build -a -ldflags '-extldflags "-static"' -o docker/x86_64/nfs-client-provisioner ./cmd/nfs-client-provisioner build_arm: - CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build -a -ldflags '-extldflags "-static"' -o docker/arm/nfs-client-provisioner ./cmd/nfs-client-provisioner + go build -a -ldflags '-extldflags "-static"' -o docker/arm/nfs-client-provisioner ./cmd/nfs-client-provisioner image: docker build -t $(MUTABLE_IMAGE) docker/x86_64 docker tag $(MUTABLE_IMAGE) $(IMAGE) image_arm: - docker run --rm --privileged multiarch/qemu-user-static:register --reset docker build -t $(MUTABLE_IMAGE_ARM) docker/arm docker tag $(MUTABLE_IMAGE_ARM) $(IMAGE_ARM) Only in /tmp/nfs-client/deploy: .deployment-arm.yaml.swp diff -ur ./deploy/deployment-arm.yaml /tmp/nfs-client/deploy/deployment-arm.yaml --- ./deploy/deployment-arm.yaml 2020-06-28 09:24:48.499572298 +0000 +++ /tmp/nfs-client/deploy/deployment-arm.yaml 2020-06-28 10:06:11.876117004 +0000 @@ -4,7 +4,8 @@ name: nfs-client-provisioner labels: app: nfs-client-provisioner - namespace: nfs + # replace with namespace where provisioner is deployed + namespace: default spec: replicas: 1 strategy: @@ -20,7 +21,7 @@ serviceAccountName: nfs-client-provisioner containers: - name: nfs-client-provisioner - image: 192.168.1.114:5000/nfs-client-provisioner-arm + image: quay.io/external_storage/nfs-client-provisioner-arm:latest volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes @@ -28,11 +29,11 @@ - name: PROVISIONER_NAME value: fuseim.pri/ifs - name: NFS_SERVER - value: 192.168.1.145 + value: 10.10.10.60 - name: NFS_PATH - value: /mnt/data/kubedata + value: /ifs/kubernetes volumes: - name: nfs-client-root nfs: - server: 192.168.1.145 - path: /mnt/data/kubedata + server: 10.10.10.60 + path: /ifs/kubernetes diff -ur ./deploy/test-pod.yaml /tmp/nfs-client/deploy/test-pod.yaml --- ./deploy/test-pod.yaml 2020-06-28 09:36:06.872994438 +0000 +++ /tmp/nfs-client/deploy/test-pod.yaml 2020-06-28 10:06:11.920115180 +0000 @@ -5,7 +5,7 @@ spec: containers: - name: test-pod - image: 192.168.1.114:5000/ubuntu:20.04 + image: gcr.io/google_containers/busybox:1.24 command: - "/bin/sh" args: diff -ur ./docker/arm/Dockerfile /tmp/nfs-client/docker/arm/Dockerfile --- ./docker/arm/Dockerfile 2020-06-28 07:47:43.759177680 +0000 +++ /tmp/nfs-client/docker/arm/Dockerfile 2020-06-28 10:06:00.628585293 +0000 @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM hypriot/rpi-alpine:3.6 -RUN apk update --no-cache && apk add ca-certificates +FROM ubuntu:20.04 COPY nfs-client-provisioner /nfs-client-provisioner ENTRYPOINT ["/nfs-client-provisioner"] nfs-client/cmd/nfs-client-provisioner为Provisioner源码目录。 ...

June 28, 2020

关于建立个人知识库的思考

建立个人知识库的思考

June 9, 2020