从头开始摘树莓 - Day 3

安装 scipy

昨晚装 scipy,用 pip 装花了一个多小时,结果装完一 import scipy.fftpack,居然报不存在。

好吧,太娇气了,只能试别的操作了。

先吃后悔药:sudo pip uninstall numpy scipy

其实我们没必要用最新版本,所以先试试 apt-get,不行再从源代码编译呗。

sudo apt-get install libopenblas-base libatlas3-base
update-alternatives --list libblas.so.3
sudo apt-get install python-numpy python-scipy --reinstall

速度很快,就搞定了。但怎么检查有没有用上 BLAS 啥的呢?Stack Overflow 有网友说可以看动态库关联,他给的语句可能得改改,因为路径文件名啥的可能真的不一样,我折腾到最后用的是:

$ ldd /usr/lib/python2.7/dist-packages/numpy/core/multiarray.arm*
 linux-vdso.so.1 (0x7ea74000)
 /usr/lib/arm-linux-gnueabihf/libarmmem.so (0x76e32000)
 libblas.so.3 => /usr/lib/libblas.so.3 (0x76dca000)
 libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0x76d4b000)
 libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0x76d22000)
 libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0x76be3000)
 /lib/ld-linux-armhf.so.3 (0x76f99000)
 libopenblas.so.0 => /usr/lib/libopenblas.so.0 (0x76453000)
 libgfortran.so.3 => /usr/lib/arm-linux-gnueabihf/libgfortran.so.3 (0x7639e000)
 libgcc_s.so.1 => /lib/arm-linux-gnueabihf/libgcc_s.so.1 (0x76371000)

所以算是有的了。再试试 import scipy.fftpack,也正常,那就完事了。

回过头来再跑程序,逐步解决了如下问题:

  1. 诶怎么 matplotlib 没了?那就再来:sudo apt-get install python-matplotlib
    (其实最早我试的 pip 安装 pip install -U matplotlib -i https://pypi.mirrors.ustc.edu.cn/simple,然后我就看到 pip 默默地又把我卸掉的 numpy 装回来了……于是它编译的时候我就迅速 Ctrl+C 了)
  2. 接着报没装 skimage,那就:sudo apt-get install python-skimage
  3. 继续 sudo pip install loky -i https://pypi.mirrors.ustc.edu.cn/simple

终于,能运行了。

设置自启动

差点忘记设置服务器自启动了。之前弄这个有好多坑,反正到最后翻了好多网上的做法,我的选择简单粗暴(先感谢 AskUbuntu ):

sudo nano /etc/rc.local

# 增加以下内容,注意 rc.local 运行的时候就是 root 权限的
exec 2> /tmp/rc.local.log # send stderr from rc.local to a log file
exec 1>&2 # send stdout to the same log file
set -x # tell sh to display commands before execution

python /home/pi/IPBroadcaster.py &
python /home/pi/cubik/server/server.py &
# echo `date +%Y-%b-%d_%H:%M:%S` > /tmp/ran_rc_local # check that rc.local ran
exit 0

回头解决代码问题

距离我还在埋头处理线程问题,已经经过了两天。终于我可以好好调试这个鬼问题了。

在这个项目里,线程安排是这个样子的:

  • 主进程运行过程中需要处理信号和 socket,而我们有一个运行时间很长的 taskInstance 线程,它按需开始结束,没有对主进程的环境依赖(准确来说,它有可能收到强退信号,但这个信号不能让主进程也强退了),需要有 Pipe 与主进程通信
  • taskInstance 线程运行过程中有一个 multiprocessing pool,同时运行几个 CPU 占用较多的 Python 任务(姑且叫做 visualSubtask 吧,反正里面东西不是我写的),输入输出需要能方便地传 Python 的数据类型,运行过程中最多就是 print 一些调试信息,倒不需要中途用 Pipe 传数据;同样,它有可能收到强退信号,但这个信号不能影响主进程强退

之前我是想试图解决信号的问题。实际上因为大部分的 forking 都是在加载完服务器程序之后进行的,所以对子进程发出的所有信号总会被服务器的信号处理代码截获,于是会导致主程序重启。

一种解决方案是在服务器程序加载之前做 prefork,把 taskInstance 的 process 先创建了。然而因为 taskInstance 是按需开始结束的,这样对它内部运行的改动还是挺大的(不过这部分代码是我写的,也不算麻烦,它也不会有长时间计算,轮询接收外头信号还是很容易,就是流程时序要求比较高)。更大的问题是,如果 taskInstance 意外停止了,之后要初始化它的那个“纯净”的环境就有点困难了。后面的路走不通的话,就还是得乖乖这么做了。

在逛 StackOverflow 的过程中看到有人推销自己写的 loky 库,似乎可以实现在程序运行中途 fork 一个纯净环境出来(Reusable executor)。两天前的中午我试了下,结果报错 Cannot pickle connection object. This object can only be passed when spawning a new process(传 Pipe 进子程序是我们程序必须要做的)。于是就得查查怎么把 connection object pass in before spawning a new process 咯。然而这库文档真的少得不行,只能仔细再研究看看了。

尝试许久,发现几个问题:

  1. 自己的 Pipe 传不进去。用事先在主线程定义好,子线程 global,得到的 Pipe 是坏的(查了下,说是升级到 Python 3+ 就好了,然而代码还有别人写的部分,懒得升级);说用 initializer 的 initargs 传进去,我硬是自己拿 loky 的 context 出来,把里面 Manager 的生成语句改了,加上自己的 initializer,再传给 get_reusable_executor 去用,结果啥都没收到,initializer 也没 print 东西出来。(感觉这个 Manager 程序根本没用到吧,放弃。)
  2. 会有 defunct 进程,感觉这个是 BUG。啥都没干只 get_reusable_executor 一次,结果 cherrypy 会根据代码更新自动重启,重启的时候  /usr/bin/python -c from loky.backend.semaphore_tracker import main; main(3) 这个进程似乎是没处理好,就 defunct 了,Ctrl+C 的时候倒是这些进程就消失了。

所以,还是得改成提前创建 taskInstance 的进程的方式,这时候我倒是觉得可以参考 http://www.defuze.org/archives/198-managing-your-process-with-the-cherrypy-bus.html 里 Broker 工作的方式重写下程序啦。

P.S. 送一条 OpenCV 3 + Python 3 的指令 cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D INSTALL_C_EXAMPLES=OFF -D INSTALL_PYTHON_EXAMPLES=OFF -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules -D WITH_TBB=ON -D BUILD_TBB=ON -D WITH_OPENMP=ON -D BUILD_EXAMPLES=OFF -D WITH_NVCUVID=ON -D WITH_CUDA=ON -D BUILD_DOCS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_TESTS=OFF -D WITH_OPENCL=ON -D PYTHON_EXECUTABLE=$HOME/.virtualenvs/cv/bin/python3.5 -D PYTHON3_NUMPY_INCLUDE_DIRS=$HOME/.virtualenvs/cv/lib/python3.5/site-packages/numpy/core/include ..

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

To respond on your own website, enter the URL of your response which should contain a link to this post's permalink URL. Your response will then appear (possibly after moderation) on this page. Want to update or remove your response? Update or delete your post and re-enter your post's URL again. (Find out more about Webmentions.)