Fork me on GitHub

caffe源码编译安装要点

  • 编译ImageMagick:

    ./configure --prefix=/home/***/*** --with-quantum-depth=8 --without-x --without-xml --without-tiff --without-openexr --without-fontconfig --without-freetype --with-jpeg=yes --disable-openmp --disable-docs LDFLAGS="-L/home/***/***/lib" CPPFLAGS="-I/home/***/***/include"
  • openblas编译:

    修改 CC = ~/.jumbo/opt/gcc46/bin/gcc,FC = ~/.jumbo/opt/gcc46/bin/gfortran,COMMON_OPT = -O2
    注释COMMON_PROF = -pg
  • 编译protobuf:

    修改src/google/protobuf/io中的kDefaultTotalBytesLimit和kDefaultTotalBytesWarningThreshold,去除message=64M的限制,重新编译安装
    CXXFLAGS="-O3 -fPIC" ./configure --prefix=/home/tcheng/protobuf/ --enable-shared --enable-static
    这样编译出来可移植的静态库
  • boost编译安装:(最好安装在系统目录下)

    ./bootstrap.sh --prefix=path/to/installation/prefix
    ./b2 install
    静态库增加-fpic选项的方法: 
    http://blog.csdn.net/lzshlzsh/article/details/50110771
  • Opencv的安装:

    mkdir build && cd build && ccmake .. 
    a. 安装的时候最好去除各种不必要的选项,避免最终编译连接时,需要引入各种静态库
    b. 动态库和静态库需要分别编译,动态库用于caffe编译,静态库用于服务编译
    c. Png和Jpeg库最好从Opencv带的3rdparty源码中编译出来,有版本限制,最好将系统自带库升级到相应版本以上,注意升级原有libpng相关的代码
    d. 注意opencv 编译的时候,需要检查依赖库的路径,是否指向的是期望的版本,存在多个版本的时候会出现编译使用的不是期望版本的问题。
    e. cuda 8.0 需要 opencv 2.4.13 的版本,老版本编译有错
  • caffe安装:

    修改Makefile.config,make all, make test, make runtest
    caffe需要修改CUDA_CHECK宏,避免程序结束资源释放出错的问题
    CUDA 8.0+CUDNN 5的时候需要修改源代码,根据出错信息调整函数名称或者参数

并行执行任务的 shell 脚本

工作中有时会需要跑一些任务处理的脚本,其处理的任务相对单一,但数据量大,导致单次运行脚本的时间比较长,如果任务是互相独立并且是可以分片的,那么,并行处理无疑是更快的方式。

在 shell 中,可以使用管道,生产者-消费者模型来实现任务的并行处理。下面提供一个 shell 脚本,自定义其中的 run 函数,可以实现指定并发度的并行:

#!/bin/sh

# 定义同时执行的任务数量,相当于并发度
SUB_PROCESS_NUM=20

# 参数解析,-s: 设置SUB_PROCESS_NUM,即并发度; -h: 输出帮助信息
while getopts :s:h opt
do
    case $opt in
        s) let SUB_PROCESS_NUM=OPTARG+0 ;;
        h) echo -e "Usage\n"
           echo -e "\t$0\t-s\tCocurrnet subprocess num\n"
           echo -e "\t\t\t-h\tPrint this help info\n"
           echo -e "\tAny questions pls feel free to contact  frostmourn716@gmail.com\n"
           exit 0;;
        *) echo "unknown option: $opt" ;;
    esac
done

#准备命名管道
tmpfile="$$.fifo"
mkfifo $tmpfile
exec 6<>$tmpfile
rm -rf $tmpfile

#producer写入任务标记
for ((i=1; i<=$SUB_PROCESS_NUM; i++))
do
    echo "sub job"
done >&6

# 需要自定义的任务函数,比如这里是发送请求
run(){
    ts=`date +%y%m%d%H%I%S`
    echo -e "$ts\tprocess $1"
    curl -s -X POST --data-urlencode "content@$1" --data-urlencode "id=$RANDOM" "http://*.*.*.*:8080/test.php" >/dev/null 2>&1
}

# 具体分配执行任务的代码,以处理图片为例,遍历图片,以指定的并发度处理任务
# 每个任务执行结束之后会将标记写入管道,当管道中存在任务标记时,代码会读出并且启动下一个任务
for image in `ls ./images/*`
do
    read line
    (run "${image}" >> ./log 2>&1; echo "sub job") >&6 &
done <&6

一些 shell 片段

记录一些 shell 片段,日常运维开发工作中方便使用:

  1. IP 列表排序

    sort -t'.' -k1,1n -k2,2n -k3,3n -k4,4n
  2. shell 命令获取唯一 id 的一种方法

    openssl rand -hex 12
  3. 获取使用了特定文件的进程 ID

    /sbin/fuser -v [文件路径]
  4. 添加帐号与删除帐号

    #!/bin/bash
    USERNAME=$1
    PASSWD=$2
    echo "adding user ${USERNAME}..."
    useradd -d /data/${USERNAME} -m ${USERNAME} && echo ${PASSWD} | passwd --stdin ${USERNAME} && chmod 755 /data/${USERNAME} && echo "succeed"
    userdel -r ${USERNAME}
  5. 转置文件(每行列数相同)

    #!/bin/bash
    awk 'BEGIN{ORS=""} {
        for(i=1;i<=NF;++i){
            contents[i,NR]=$i;}
        } 
        END{for(x=1;x<=NF;++x){
                for(y=1;y<=FNR;++y){
                    print contents[x,y];
                    if(y<FNR){print " ";
                }
            };
            if(x<NF){print "\n";}
    }}' file.txt

一些有用的 Github 小项目

记录一些有用的 Github 工具类型的项目,经常需要的时候找不到,现找又很费时间,记录在此:

  • 代理列表:https://github.com/fate0/proxylist,包含国内外的透明、匿名、高匿的 http 和 https 代理,7分钟更新一次。顺道提供一段脚本,自动解析属地在中国的高匿 https 代理,如下:

    #!/bin/sh
    curl -s 'https://raw.githubusercontent.com/fate0/proxylist/master/proxy.list#' | grep 'high_anonymous' | grep '"CN"' | grep '"https"' | awk 'BEGIN{OFS=":"} {if(match($0, /\"host\": \"([0-9\.]+)\".*\"port\": ([0-9]+)/, a)){print a[1], a[2]}; if(match($0, /\"port\": ([0-9]+),.*\"host\": \"([0-9\.]+)\"/, a)){print a[2], a[1]};}'
  • 超级速查表:https://github.com/skywind3000/awesome-cheatsheets,常用命令小卡片,主要包括 Bash,GDB,VIM 等
  • 待更新...

记 CentOS 7上一个诡异的性能问题

问题背景

线上系统从 CentOS 6 迁往 CentOS 7,整个过程较为顺利,但在使用中发现了一个奇怪的问题,在处理计算任务的机器上,CPU计算部分的耗时在不同节点上存在差异且差异显著,如下图所示:

A12280BA-1D10-4FC6-8C61-66C73A1A424B.png

出问题的机器计算耗时波动剧烈,耗时差别达到30%~50%,极端的 case 会更高,但并非所有机器、所有请求都受到影响。在初期问题机器只集中在个别机器和高峰时间段,高峰过后就会恢复,到后期则是随机的机器和全时间段,压力退去之后也不能恢复,重启大法也不能奈何。
这个问题的诡异之处就在于它的飘忽不定,定位经历了很长时间,也是很偶然的看到一篇文章才解决了问题

解决过程

CentOS 7集群上线之初由于存在两种机型,差别仅在于磁盘的区别,而出问题的机器则集中在同一种机型上,所以开始很自然的认为是机器配置导致的问题,观察各项监控,发现 cpu.system占用较高,说明有频繁的系统调用,最常见的情况自然是 IO 有问题,排查网络交互均正常,内存看不出问题,加上磁盘本身就存在区别,程序又有大量的日志输出,监控 agent 一直槽点多多,怀疑的重点转移到磁盘读写这块儿了,刚好磁盘的监控确实也有点不同(下图中下方红线部分):

A5B1559E-2447-476A-8BB1-BC8712399D0A.png

由于代码都是原来的一套,在原来的机器上也没有问题,那么性能更强的新机器上,出问题的概率也很小,那么问题很可能是出现在读日志的监控 agent 上了,鉴于新agent 属于第一次使用,本身 cpu 占用率也很高,在各项指标都指向它且没有强力证据自证清白,只好当仁不让的背起了这口锅(当然最后事实证明并不是 agent 的原因,记录事情发展经过)。排除 agent 的可能后,再回过头来反复观察对比各项监控(top,vmstate,iostate,sar 以及系统监控等),除了cpu.system,cpu.context_switch,load 等始终存在区别,其它指标时常反复,没有什么线索。考虑到已花了较多的时间,而且只有固定的几台有问题,干脆在机型替换时直接换掉,一了百了。

但问题在替换机器之后发生了很大的变化,如下图:

DBEDD890-94AF-491F-A44B-917B25C6CBC3.png

在替换之前,只有固定的机器在高峰期耗时变长,而替换之后,原本正常的机器也随机的开始不正常,并且在高峰过后,这种不正常的状况会一直持续,无法自行恢复,仿佛进入了一种混沌的状态。这下问题就有点严重了。

重新集中观察对比各项监控指标,除了system 和 context_switch 之外,此时又观察到 softirq 以及 migration 进程存在区别。同时,设计实验证明,在异常时,并非整机有问题,而是部分请求(或者说部分进程)出现长耗时,而同期其它请求正常,在继续排除了 NGXIN PHP 等常驻进程的问题后,问题范围可以缩小一些了,猜测系统配置问题的可能性较大,只是是哪个,还得找。

继续实验的同时,借助 Google,将各种已明确的指标和现象抽出关键字各种搜索,终于,很幸运找到了一篇文章,大意是从 CentOS 6 向 CentOS 7 迁移后,也发生了性能下降的问题,显著的表现也是 context_switch 和 softirq 指标显著不同,load 存在区别,性能不及预期的情况,这位仁兄在历经各种心酸血泪(各种更新内核,更换 OS重装,重装驱动等等)之后才解决,初读并没觉得和我们是一个问题,再次阅读的时候,发现其中指标差异有点类似,抱着试试的态度,尝试了一下他的解决方案,问题解决!

问题解决

方案得来不易,怎么做的就不直接剧透了,和 NUMA Balancing 有关,想了解具体情况的,点击博客贡献访问量吧。

关于 NUMA,其中一篇介绍如下:
NUMA架构的CPU — 你真的用好了么? - CSDN博客