Bringing HPC Techniques to Deep Learning

原文地址: andrew.gibiansky.com/bl

Allreduce 其实一直是HPC领域很常见的一个技术,所以百度这篇论文其实讲的也是如何将Allreduce从HPC引入到深度学习领域,通过Allreduce算法,大大的提高了深度学习的模型训练速度

简介

过去几年中,神经网络规模不断扩大,而训练可能需要大量的数据和计算资源。 为了提供所需的计算能力,我们使用高性能计算(HPC)常用的技术将模型缩放到数十个GPU,但在深度学习中却没有充分使用。 这种ring allreduce技术减少了在不同GPU之间进行通信所花费的时间,从而使他们可以将更多的时间花费在进行有用的计算上。 在百度的硅谷AI实验室(SVAIL)中,我们成功地使用了这些技术来训练最先进的语音识别模型。 我们很高兴将Ring Allreduce的实现发布为TensorFlow的库和补丁程序,并希望通过发布这些库,我们可以使深度学习社区更有效地扩展其模型。

Introduction

在过去的几年中,神经网络已被证明是解决各种问题的非常有效的工具,并且在规模和计算需求方面迅速增长。 2012年,用于图像识别的SuperVision卷积网络通过两个星期的GPU和6000万个参数在对象识别方面取得了长足的进步。 2016年,研究人员在网络上进行语言建模方面取得了突破,该网络具有在32个GPU上进行了为期三周的训练的十亿多个参数。 在百度研究院的硅谷AI实验室中,2014年,我们的Deep Speech语音识别系统的第一次迭代大约有1100万个参数,而一年后的下一次迭代已增长到1亿个参数。

随着神经网络的参数数量和计算需求的增长,在许多节点和许多GPU上有效并行化神经网络训练变得越来越重要,因为等待大型网络训练数月会减慢实验速度并限制进一步的发展。 在此博客文章中,我们介绍了一种来自高性能计算(HPC)领域的技术,并演示了如何将其应用于深度学习以在神经网络训练中获得显着的性能提升。


sony xz2p do版本最全app清理列表

由于日版 docomo 有芯片锁,无法解锁bl,也无法 root,目前唯一的办法只能通过 adb 删除自带软件已达到精简目的

adb 怎么安装怎么用自行百度,目前只贴 app 的清理列表。可以直接保存为 bat 文件,执行即可

adb shell pm uninstall –user 0 com.amazon.mShop.android.shopping

adb shell pm uninstall –user 0 com.google.android.calendar

adb shell pm uninstall –user 0 jp.co.nttdocomo.lcsapp

adb shell pm uninstall –user 0 com.sonymobile.scan3d

adb shell pm uninstall –user 0 com.google.android.youtube


cgroup 内存管理之 tmpfs

1. tmpfs 内存简介

tmpfs 文件系统是 pod 中常见的一种“存储”介质,也叫 ram disk,都是一个东西
tmpfs 的特殊的地方在于:
  1. 首先它是个文件系统
  2. 但是它的文件数据是完全存放在内存里面的,不在磁盘上
所以要讲 tmpfs 的话,就得把这两部分都讲清楚,一个是文件系统的实现,一个是底层“持久化”层内存的管理
通常应用程序之间会通过 tmpfs 文件系统来实现高效的数据共享
/dev/shm 就是一个最典型的 tmpfs 文件系统,是操作系统为了解决大多数程序数据共享而默认挂在的一个 tmpfs

2. tmpfs 文件系统的实现

我们知道 file 是linux内核最重要的设计,一切皆文件
除了普通的文件,平时我们接触到的,unix管道、socket、proc、cgroup 等等,都是基于文件的实现
为了实现灵活可扩展的文件系统架构,Linux设计了 virtual file system 抽象层,简称 vfs,对用户台程序屏蔽了所有具体的底层文件系统的实现细节,提供统一的文件系统接口

2.1. virtual file system 接口定义

vfs 属于一个专题,我们这里不讲那么复杂,有时间可以专门展开讲
vfs 定义了文件系统实现最关键的2个接口:
  1. 一个是 struct file_operations:文件读写的接口
  2. 一个是 struct inode_operations:inode操作接口
inode_opertions 定义如下:
struct inode_operations {
        int (*create) (struct user_namespace *, struct inode *,struct dentry *, umode_t, bool);
        int (*symlink) (struct user_namespace *, struct inode *,struct dentry *,const char *);
        int (*mkdir) (struct user_namespace *, struct inode *,struct dentry *,umode_t);
        int (*rmdir) (struct inode *,struct dentry *);
        /* 省略一万字 */
};
是不是很熟悉?


主成分分析(PCA)简明过程

主成分分析(PCA)是最常见的降维算法,通常用于数据压缩以及噪音过滤

比如我们可以通过PCA将100维的向量最后用10维来表示,那么压缩率为90%,同时还可以保证数据的特性损失尽可能的小

1)PCA算法流程

在详细展开讲之前,先了解一下几个基本数学符号的定义:

x^{i} 表示第i个样本数据(这个数据是一个N维向量)

x_{j}^{i} 表示第i个样本的第j个特征

x_{j} 表示由所有样本数据的第j个特征变量组成的一个向量

了解这些数学符号的定义非常重要,否则后面的推导公式很容易混乱

假设我们有一个n维的样本数据集 D = (x^{(1)}, x^{(2)}, ..., x^{(m)}),其中每一个数据都是n维的 x^{(i)} = \{x_1^i, x_2^i, ..., x_n^i\},我们要把维度从n维降到k维:

  1. 对所有样本进行归一化 x^{(i)} = x^{(i)} - \frac{1}{m} \sum\limits_{j=1}^{m} x^{(j)}
  2. 计算协方差矩阵covariance matrixXX^T,其中 X 的定义非常重要
  3. 计算协方差矩阵XX^T特征向量eigenvectors),通常用SVD分解,得到 [U, S, V]
  4. 从U中选取前k个最大特征值对应的特征向量,组成一个新的特征向量矩阵U_{reduce}
  5. 对所有样本,求的新的降维后的样本,z^{(i)} = U_{reduce}^T * x^{(i)}


x230 再战黑苹果 10.14.5

距离上一次安装黑苹果,已经3年过去了。第一次安装的时候作为一个新手,参考网上教程,整个安装过程顺利的让我这种小白都震惊了,x230 不愧是为黑苹果而生的一个本本

但是后来因为网卡问题,安装后就没有继续用了,切记!使用黑苹果千万别用usb网卡,那真是非常蛋疼,能上网但是进不去 app store 的,因为 app store 必须要求网卡BSD名字是en0。虽然有一些魔改的教程,但是成功率不高,不建议尝试,比较浪费时间

x230 上黑苹果能用的网卡主流是2种,一种是AR9285,一种是BCM94352,BCM的高级很多,AR的最傻瓜凑合用。我淘了一个AR的把原装网卡换掉了。接下来准备开始安装黑苹果,但是这次就没那么顺利了,为了防止下一次继续掉坑,记录了一下安装过程需要特别注意的一些地方

安装黑苹果的过程可以分为4大块

  1. BIOS 参数修改
  2. 制作U盘启动盘(EFI + 原始镜像)
  3. 安装(硬盘分区,安装)
  4. 硬盘引导

其中网上大部分傻瓜教程或者视频,都是讲2-4,但其实1非常关键,你看那些教程视频装个黑苹果跟装个Windows似的,因为很多前置的坑都填了(就比如BIOS参数),当然是看着很简单了。


cgroup 内存管理之 page cache 回收

page cache 的管理,是内核内存管理里最复杂的一块,也是容器混部场景下,问题最多的地方
我们这里只关注读 cache 的处理,脏页的控制单独讲。所以这篇文章里,无特殊说明 page cache 默认不包括脏页部分
当我们谈到 page cache 时, 我们会关注什么?
有以下几个关键的点
  1. 什么时机会触发 page cache 回收?
  2. 回收过程是什么样的
  3. 不可回收的页面有哪些?
  4. 不容易回收的页面有哪些?
  5. 回收力度如何控制
接下来,我们就这几点,来讲一讲 page cache 的一些内核实现内幕。以及混部场景下,可能会遇到的一些坑
实际上,不同的回收方式,其时机、回收的页面范围、力度、算法都稍有不同,所以下面我们将按照不同的回收方式来详细讲

1. 整机 drop_caches 回收

内核接口 /proc/sys/vm/drop_caches
内核的代码实现入口在 fs/drop_caches.c 里面
这个接口支持3种方式:
  1. echo 1,清理 page cache
  2. echo 2,清理 slab,比如 dentry cache 通常也很消耗内存
  3. echo 3,两种都清理
我们这里只讨论方式1

1.1. 回收时机、力度、算法

只有人为的 echo xx > /proc/sys/vm/drop_caches 时,才会触发 page cache 回收
每次触发 drop_caches,基本上都会把系统能回收的 clean page 一次性全部回收回来,注意,是全部能回收的
所以,这里其实也没有什么的特殊的回收算法了,简单全遍历就完了

1.2. 回收过程

内核代码 fs/drop_caches.c
简单来说,就是
  1. 遍历所有的超级块,super_block
  2. 遍历每个超级块上的所有 inode 对象
  3. 根据 inode->i_mapping 找到每个 inode 的 address_space 空间
  4. 遍历 address_space 下的所有 page
    1. 将 page 从 radix tree 上删除
    2. 调用文件系统的 releasepage 函数释放文件系统资源。这个可以忽略,我看 fs/* 几乎所有文件系统都不实现这个函数了
  5. 释放所有能释放的 page 内存(引用计数为0)
核心逻辑的调用栈如下:
  • drop_caches_sysctl_handler
    • iterate_supers(drop_pagecache_sb, NULL)
      • drop_pagecache_sb, list_for_each_entry(inode, &sb->s_inodes, i_sb_list)
        • invalidate_mapping_pages(inode->i_mapping, 0, -1) // 这个函数的实现在 mm/truncate.c 文件里,Invalidate all the unlocked pages of one inode
          • invalidate_inode_page(page) for page in pagevec_lookup_entries(&pvec)
            • invalidate_complete_page() 删除page的mapping,并从 page cache 的radix-tree 里面剔除,因为下一步就直接 free 内存了
        • pagevec_release(&pvec) // 释放所有的 page 内存空间

1.3. 回收范围

drop_caches 是一个非常轻量级的回收过程,只回收能够立即释放的 page
从 invalidate_inode_page() 我们可以看到,有3种页面,是不会被回收的:
  1. 脏页
  2. 正在回写的页
  3. mmap + MAP_SHARED 方式映射到 page table 的页
  4. PG_SyncReadahead 需要多次drop才能回收
int invalidate_inode_page(struct page *page)
{
        struct address_space *mapping = page_mapping(page);
        if (!mapping)
                return 0;
        if (PageDirty(page) || PageWriteback(page))
                return 0;
        if (page_mapped(page))
                return 0;
        return invalidate_complete_page(mapping, page);
}
注意,page_mapping() 和 page_mapped() 不是一个东西。另外,!mapping 这段代码我没看懂是过滤的啥?
page_mapping() 返回 page 的 address_space,读的是 page->mapping 信息
(1)返回 NULL,说明该页要么是 slab cache,要么是 anon
(2)返回非空,可能是 swap_address_space(),或者就是正常页所在的一个 address_space
struct address_space *page_mapping(struct page *page)
{
        struct address_space *mapping;
        page = compound_head(page);
        /* This happens if someone calls flush_dcache_page on slab page */
        if (unlikely(PageSlab(page)))
                return NULL;
        if (unlikely(PageSwapCache(page))) {
                swp_entry_t entry;

                entry.val = page_private(page);
                return swap_address_space(entry);
        }
        mapping = page->mapping;
        if ((unsigned long)mapping & PAGE_MAPPING_ANON)
                return NULL;
        return (void *)((unsigned long)mapping & ~PAGE_MAPPING_FLAGS);
}

而 page_mapped 是用来判断 page 是否在 page table 里面。这里用 page_mapped() 主要是用来判断当前 page 是否是一个 mmap + MAP_SHARED 产生的页(因为 MAP_PRIVATE 产生的页不会填充到 page table 里面,具体可以自己看下代码)


cgroup 内存管理之 mlock

我们在使用容器的过程中,可能会遇到一个问题,容器利用率很低,但是经常发生 oom,这是什么情况?
很可能是业务使用了一些不可回收的 page cache,其中最主要的应该就是 mlock

1. mlock 的背景

mlock 的作用就是防止页面被换出到 swap 分区,或者 page cache 被内核回收
由于线上服务器,基本默认都会关闭 swap 分区,所以这种情况暂不讨论,防止 page cache 被内核回首是主要作用
什么样的 page 需要 mlock?
1)通过 mmap 方式映射到内存中的 page cache,比如一些关键的索引数据,需要经常访问,那就得 mlock 住,否则 pgmajfault 带来的性能抖动是很大的
2)程序自身依赖的一些 so 动态链接库,由于内核的 page cache 回收算法,并不感知 page 具体是普通的文件 cache,还是 so 动态链接库,所以当容器内存不足时,内核通过一些粗略的回收算法回收 page cache,一旦把 so 的缓存页回收掉了,程序在调用相关函数时,会出现严重的性能抖动
因此,通过 mlock,显式的把一些关键的不希望被回收的 page cache 锁定起来,达到保证业务性能的目的


AllReduce 算法的前世今生

原文:https://zhuanlan.zhihu.com/p/79030485

从事分布式深度学习相关工作的同学,应该都频繁地用到了AllReduce(规约)操作。

图1 AllReduce的示意图

但是对于训练框架中集成的AllReduce相关操作,其背后实现的原理是什么?

除了最近几年名声大噪的Ring AllReduce是否还有其他的AllReduce算法?

他们各自的性能开销如何?如何取舍?

本文尝试从一个较为全面的角度来展现AllReduce算法的前世今生,既分析经典算法,也介绍发展中的新秀。

MPI中的AllReduce算法

其实说到AllReduce,很多人脑海里的第一反应都是MPI_AllReduce。作为集合通信中的元老,和高性能计算领域的通信标准,在MPI_AllReduce这个通信原语背后,MPI中实现了多种AllReduce算法。

以openMPI源码为例,里面实现了多种allreduce的算法。具体的算法选择在

ompi/mca/coll/tuned/coll_tuned_decision_fixed.c

图2 openMPI源码中选择allreduce算法的代码片段

Dynamic writeback throttling

https://lwn.net/Articles/405076/
Dynamic writeback throttling最主要的核心思想就是IO带宽估算。
the bandwidth estimation allows the kernel to scale dirty limits and I/O sizes to make the best use of all of the devices in the system, regardless of any specific device’s performance characteristics.
传统writeback机制的做法是,当进程脏页超过一定比例时,调用balance_dirty_pages()函数进入同步写dirty pages过程,直到dirty pages的比例下降到一定比例,之后才允许该进程返回。
该机制存在三个问题:
  1. 进程脏页比率多少才合适?
  2. 内存压力太大时,多个后台进程同时writeback,会产生大量的随机IO,设备吞吐量下降
  3. 如何更准确的估算设备的真实带宽?
Dynamic writeback throttling的基本做法是:启发式的计算设备的真实带宽,所有进程不再同步writeback改由sleep一段时间,等待后台线程统一writeback。


理解 LSTM 神经网络

LSTM 的论文原址:http://www.bioinf.jku.at/publications/older/2604.pdf

英文原文:http://colah.github.io/posts/2015-08-Understanding-LSTMs/

本文在 https://blog.csdn.net/Leo_Xu06/article/details/78141321 的翻译基础上做了一些修改

递归神经网络(Recurrent Neural Network, RNN)

人类每时每刻的思考都不是孤立的从头开始,就像你在阅读这篇文章时,你对每个词的理解都是基于对先前词的理解而产生的,因为你的想法是具有时序关联性的。

传统神经网络的一个主要缺点是——做不到信息的时序关联。举个例子,想象一下你想区分一个电影某个时间点所发生的事件,传统的神经网络就做不到根据之前的事件来推理得到下一个事件。

递归神经网络(RNN)可以解决这一问题,它的网络结构中存在回环,使得之前的信息得以保留。

0

上面的示意图中,模块 A 接受输入x_t,并输出 h_t,环形结构允许信息从一个网络状态转移到下一个网络状态。

这些循环让循环神经网络看起来有点神秘。但是,你再仔细想下,就会发现它们与常见的神经网络没有什么不一样的地方。循环神经网络可以被认为是同一网络的多个副本,每个副本向后继者传递一个消息。把它展开之后是这个样子的:

0

该链式结构揭示了RNN与序列(sequences)和列表(lists)紧密关联,用这种神经网络结构处理特定数据(文本,语言等)也是直观自然的。在过去的几年中,已经有一些难以置信的RNN成功应用案例来解决各种问题:语音识别、语言建模、翻译、图片字幕……这个名单还在不断扩展,相关讨论见Andrej Karpathy的博文:The Unreasonable Effectiveness of Recurrent Neural Networks

这些成功背后的本质是“长短期记忆模型(LSTMs)”的使用,这是一种特殊的递归神经网络,它对很多任务都适用,而且相较于标准的RNN模型,它的性能要高出许多,几乎所有基于RNN令人激动的成果都是由它取得。本文也将探索这些 LSTM 模型