加快TensorFlow在树莓派上的执行速度——服务常驻内存 – 编码无悔 / Intent & Focused

来源: [原创] 加快TensorFlow在树莓派上的执行速度——服务常驻内存 – 编码无悔 / Intent & Focused

转载请注明出处:http://www.codelast.com/

本文软硬件环境:
树莓派:3代 Model B V1.2,内存1GB
OS:Arch Linux ARM

上一篇文章中,我尝试了加快TensorFlow预测速度的一个方法——模型“预热”,实验证明它非常有效,但那仍然没有解决一个问题:每次运行程序,都要加载一次模型,然后预热N次,这个过程非常耗时,因此减少这部分时间也是非常关键的。把TensorFlow做成一个常驻内存的服务就可以解决这个问题。

『1』简单的思路
服务端,用Python实现一个web server,处理HTTP Get请求,通过解析URL中的参数(例如 http://127.0.0.1:8080/?image_path=/root/abc.jpg 中的 /root/abc.jpg),来获取待处理的图片的路径,处理完之后,把处理结果返回给客户端。
客户端,通过 curl 命令就可以调用服务了,例如:

curl http://127.0.0.1:8080/?image_path=/root/abc.jpg

这表示让服务端处理 /root/abc.jpg 这个文件。
当然,为了简单,这里的设定有一个局限:server和client都在同一个树莓派上,如果要跨机器,那么需要client把图片post到server端,server取出来之后再处理,但本文不涉及这种情况。
文章来源:http://www.codelast.com/
『2』简单Python web server的实现
不考虑什么并发,多线程之类的情况,我们可以用非常简单的一点代码就实现一个Python web server。

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/python3.5                                                                                              
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import parse_qsl
class MyRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
# e.g. "/?image_path=/root/mobike.jpg"                                                                                                                  
path = self.path
# e.g. "/root/mobike.jpg"                                                                                                                               
image_path = parse_qsl(path[2:])[0][1] + '\n'
# send response status code                                                                                                                             
self.send_response(200)
# send headers                                                                                                                                          
self.send_header('Content-type','text/html')
self.end_headers()
# send message back to client, write content as utf-8 data                                                                                              
self.wfile.write(bytes(image_path, "utf8"))
return
def start_web_server():
print('Starting web server...')
server_address = ('127.0.0.1', 8080)
httpd = HTTPServer(server_address, MyRequestHandler)
httpd.serve_forever()
start_web_server()

其中,在 MyRequestHandler 这个类中,我们会处理每一个客户端的请求,这里只是把从URL中解析到的图片文件路径简单地发送回客户端。
此代码可在我的GitHub中下载。
文章来源:http://www.codelast.com/
『3』TensorFlow服务测试
按“模型加载1次,预热10次”的原则,再结合上面的简单web server代码,我们可以很容易地把TensorFlow做成服务。具体代码比较长,这里就不粘贴上来了,在我的GitHub可以下载到。

下面测试一下效果。
把service启动起来:

1
./run-tensorflow-service.sh

经历几十秒的漫长等待之后,模型加载&预热就完成了(命令行输出会有提示),此时,我们再在同一台树莓派上运行client,向server发送一个处理图片的请求:

1
./client.sh /root/raspberry-pi/ai/tensorflow-related/resource/test-images/mobike.jpg

大概4秒多之后,client端会打印出如下信息:

mountain bike, all-terrain bike, off-roader (score = 0.56671)
tricycle, trike, velocipede (score = 0.12035)
bicycle-built-for-two, tandem bicycle, tandem (score = 0.08768)
lawn mower, mower (score = 0.00651)
alp (score = 0.00387)
Prediction used time:4.171393394470215 Seconds
换一张大小相仿的图片来测试,消耗的时间也是差不多的,达到了我们预期的效果。至此,它距离“实用”又更近了一步。
分享到: 更多 (0)