首先生成一个 height*weight*3 的全零 numpy 矩阵,dtype 为 uint8。

将其 RGB 中的绿色(G)通道设置为 255(纯绿色)。

然后使用 Pillow 将其保存到本地图片,最后调用 ffmpeg 命令生成对应视频。

ffmpeg 命令行参数:

ffmpeg -framerate 24 -loop 1 -i .\cache.png -pix_fmt yuv420p -t 39.540 -vcodec libx264 green_1080p24.mp4 -y

完整代码:

- 阅读剩余部分 -

图像分割任务中,input 和 target 都是图片,此时做数据增广时如果用到随机变换,例如随机翻转和旋转,则需要保证两者随机值相同,否则分割 label 就不准确。

例如变换:

self.transform = transforms.Compose([
    transforms.RandomHorizontalFlip(),
    transforms.RandomRotation(90),
    transforms.CenterCrop(480),
    transforms.ToTensor(),
    transforms.ToPILImage()
])

在使用时如果直接

image = self.transform(image)
bulb = self.transform(bulb)

则输入图片和 label 会产生不同的翻转/旋转角,造成数据不对应的问题。

- 阅读剩余部分 -

在阿里云 vgn5i 实例上部署深度学习环境,服务器系统为 Ubuntu 16.04

1. 安装 GRID 驱动

https://help.aliyun.com/document_detail/118852.html

按照此文档安装 GRID 驱动,注意 vGPU 需要使用专用的 GRID 驱动,安装普通驱动是无法识别虚拟卡的,且安装完驱动之后需要按照文档获得许可才可以实际使用 CUDA。在没有获得许可之前,虽然torch.cuda.is_available()返回的是True,但实际上到了代码中model.to(cuda)这一步还是会报RuntimeError: CUDA error: all CUDA-capable devices are busy or unavailable错误。

2. 使用 systemd + gunicorn 部署项目

这一步创建了个没有 sudo 权限的用户ob来跑项目,保证生产环境上服务器安全。代码放在/home/ob/ob_cuda_server目录下。坑点在于 systemd 中 anaconda 环境的切换,解决办法就是在 service 配置里指定环境变量 PATH 就直接是对应的 conda 下的 env/bin 目录,就不会用冲突了。

2.1 安装项目依赖

按照此文档下载 anaconda 并配置国内源

https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/

创建虚拟环境:

conda create -n ob_prod python=3.6

切换到此环境:

conda activate ob_prod

通过 conda 安装 torch:

conda install pytorch torchvision cudatoolkit=10.1 -c pytorch

通过 pip 安装其他依赖:

pip install flask opencv-python numpy

其中 opencv-python 可能会缺少一些系统 so 库,稍后运行程序时如果提示缺少某 lib 文件则需要使用 apt 安装对应的库。

2.2 配置生产环境

安装 gunicorn 进行生产环境部署以提供更好的性能:

pip install gunicorn

安装好之后可以使用gunicorn -w 8 -b 0.0.0.0:9001 main:app来部署项目看看效果

另开一个会话使用 curl 测试服务是否在线:

(base) syf@obulb:~$ curl localhost:9001
ob cuda server online!

可以看到已经返回了自定义的首页信息

确认可以运行后按Ctrl+C停止,后面用 systemd 来启动管理守护进程。

为了守护项目进程,让其后台自启运行,需要写一个 service 配置将 gunicorn 写入 systemd 服务。

新建/etc/systemd/system/ob_cuda并编辑:

[Unit]
Description=ob cuda server
After=network.target

[Service]
User=ob
WorkingDirectory=/home/ob/ob_cuda_server
Environment="PATH=/home/ob/anaconda3/envs/ob_prod/bin"
ExecStart=/home/ob/anaconda3/envs/ob_prod/bin/gunicorn -w 8 -b 0.0.0.0:9001 main:app
# gunicorn 多线程加载模型可能会造成显存不足或其他问题,如果用此部署后有问题则直接跑 flask,就可以解决:
# ExecStart=/home/ob/anaconda3/envs/ob_prod/bin/python main.py

[Install]
WantedBy=multi-user.target

保存后重新加载 systemd:

sudo systemctl daemon-reload

写成 systemd 服务后就可以直接用 systemctl 来管理服务了:

设置开机启动:

systemctl enable ob_cuda

查看服务状态:

systemctl status ob_cuda

重启服务:

systemctl restart ob_cuda

对 python 的 Flask、FastAPI 和 Spring Boot 集成的简单接口做速度对比,返回 json 格式的当前时间戳:

{
    "timestamp":1584416801569
}

同时把某个11位时间戳 json string 写死在 index.html 里,测试 Nginx 的并发量。虽然一个静态资源一个动态计算没有可比性,但是为了体现性能差距,还是把 Nginx 的并发拿来做对比。

- 阅读剩余部分 -

不知从什么时候开始,shadowsocks 开启后一直无法监听 1080 端口,当时换了 1081、1082 也不行,于是换了个比较高的 10800 端口解决了,也没当回事。今天因为要跑一个非 maven 的项目,需要在 idea 里手动配置 tomcat,默认的 JMX 端口 1099 又没法分配,而使用netstat -ano | grep "1099"又显示没有任何程序在占用这个端口,非常诡异。后来更改为 1098、1097 也是和上次 shadowsocks 同样的情况,死活绑定不上去,而 netstat 又显示没有程序占用这个端口,换成比较高的比如 11099 又可用了……

- 阅读剩余部分 -