use*_*300 30 python gpgpu multiprocessing deep-learning caffe
我正在尝试使用caffe和python进行实时图像分类.我在一个过程中使用OpenCV从我的网络摄像头流式传输,并在一个单独的过程中,使用caffe对从网络摄像头拉出的帧执行图像分类.然后我将分类结果传回主线程以标注网络摄像头流.
问题是即使我有一个NVIDIA GPU并且正在执行GPU上的caffe预测,主线程也会变慢.通常没有做任何预测,我的网络摄像头流以30 fps运行; 但是,根据预测,我的网络摄像头流最多可获得15 fps.
我已经验证了caffe在执行预测时确实使用了GPU,而且我的GPU或GPU内存并没有最大化.我还验证了我的CPU内核在程序中的任何时候都没有达到最大限度.我想知道我是做错了什么,或者是否有办法让这两个过程真正分开.任何建议表示赞赏.这是我的代码供参考
class Consumer(multiprocessing.Process):
def __init__(self, task_queue, result_queue):
multiprocessing.Process.__init__(self)
self.task_queue = task_queue
self.result_queue = result_queue
#other initialization stuff
def run(self):
caffe.set_mode_gpu()
caffe.set_device(0)
#Load caffe net -- code omitted
while True:
image = self.task_queue.get()
#crop image -- code omitted
text = net.predict(image)
self.result_queue.put(text)
return
import cv2
import caffe
import multiprocessing
import Queue
tasks = multiprocessing.Queue()
results = multiprocessing.Queue()
consumer = Consumer(tasks,results)
consumer.start()
#Creating window and starting video capturer from camera
cv2.namedWindow("preview")
vc = cv2.VideoCapture(0)
#Try to get the first frame
if vc.isOpened():
rval, frame = vc.read()
else:
rval = False
frame_copy[:] = frame
task_empty = True
while rval:
if task_empty:
tasks.put(frame_copy)
task_empty = False
if not results.empty():
text = results.get()
#Add text to frame
cv2.putText(frame,text)
task_empty = True
#Showing the frame with all the applied modifications
cv2.imshow("preview", frame)
#Getting next frame from camera
rval, frame = vc.read()
frame_copy[:] = frame
#Getting keyboard input
key = cv2.waitKey(1)
#exit on ESC
if key == 27:
break
Run Code Online (Sandbox Code Playgroud)
我很确定这是因为caffe预测减慢了一切,因为当我评论预测并在进程之间来回传递虚拟文本时,我再次获得30 fps.
class Consumer(multiprocessing.Process):
def __init__(self, task_queue, result_queue):
multiprocessing.Process.__init__(self)
self.task_queue = task_queue
self.result_queue = result_queue
#other initialization stuff
def run(self):
caffe.set_mode_gpu()
caffe.set_device(0)
#Load caffe net -- code omitted
while True:
image = self.task_queue.get()
#crop image -- code omitted
#text = net.predict(image)
text = "dummy text"
self.result_queue.put(text)
return
import cv2
import caffe
import multiprocessing
import Queue
tasks = multiprocessing.Queue()
results = multiprocessing.Queue()
consumer = Consumer(tasks,results)
consumer.start()
#Creating window and starting video capturer from camera
cv2.namedWindow("preview")
vc = cv2.VideoCapture(0)
#Try to get the first frame
if vc.isOpened():
rval, frame = vc.read()
else:
rval = False
frame_copy[:] = frame
task_empty = True
while rval:
if task_empty:
tasks.put(frame_copy)
task_empty = False
if not results.empty():
text = results.get()
#Add text to frame
cv2.putText(frame,text)
task_empty = True
#Showing the frame with all the applied modifications
cv2.imshow("preview", frame)
#Getting next frame from camera
rval, frame = vc.read()
frame_copy[:] = frame
#Getting keyboard input
key = cv2.waitKey(1)
#exit on ESC
if key == 27:
break
Run Code Online (Sandbox Code Playgroud)
一种想法可能会发生在您的代码中,即第一次调用时它在 GPU 模式下工作,而在以后的调用中,它会在 cpu 模式下计算分类,因为它是默认模式。在旧版本的caffe上设置gpu模式一次就足够了,现在新版本每次都需要设置模式。您可以尝试进行以下更改:
def run(self):
#Load caffe net -- code omitted
while True:
caffe.set_mode_gpu()
caffe.set_device(0)
image = self.task_queue.get()
#crop image -- code omitted
text = net.predict(image)
self.result_queue.put(text)
return
Run Code Online (Sandbox Code Playgroud)
另请查看消费者线程运行时的 GPU 计时。对于 nvidia,您可以使用以下命令:
nvidia-smi
Run Code Online (Sandbox Code Playgroud)
上面的命令将显示运行时的 GPU 利用率。
如果还不能解决,另一种解决方案是,将opencv帧提取代码放在一个线程下。由于它与 I/O 和设备访问相关,因此在与 GUI 线程/主线程不同的线程上运行它可能会带来好处。该线程将把帧推送到队列中,当前的消费者线程将进行预测。在这种情况下,请小心处理具有关键块的队列。