2012-06-21 43 views
12

Tôi có một ứng dụng yêu cầu xử lý nhiều hình ảnh song song để duy trì tốc độ thời gian thực.Máy tính GPU song song sử dụng OpenCV

Tôi hiểu rằng tôi không thể gọi chức năng GPU của OpenCV theo kiểu đa luồng trên một thiết bị CUDA duy nhất. Tôi đã cố gắng xây dựng một mã OpenMP như sau:

#pragma omp parallel for 
for(int i=0; i<numImages; i++){ 
    for(int j=0; j<numChannels; j++){ 
     for(int k=0; k<pyramidDepth; k++){ 
      cv::gpu::multiply(pyramid[i][j][k], weightmap[i][k], pyramid[i][j][k]); 
     } 
    } 
} 

Điều này dường như biên dịch và thực hiện một cách chính xác, nhưng tiếc là nó xuất hiện để thực hiện đề numImages serially trên thiết bị CUDA cùng.

Tôi có thể thực thi nhiều luồng song song nếu tôi có nhiều thiết bị CUDA, đúng không? Để có được nhiều thiết bị CUDA, tôi có cần nhiều thẻ video không?

Có ai biết liệu thẻ dual-chip nVidia GTX 690 hoạt động như hai thiết bị CUDA độc lập với OpenCV 2.4 trở lên không? Tôi tìm thấy xác nhận nó có thể làm việc như vậy với OpenCL, nhưng không có xác nhận liên quan đến OpenCV.

+0

Có lẽ câu trả lời nằm trong mã nguồn cho OpenCV? –

Trả lời

5

Chỉ cần nhân lên toàn bộ hình ảnh với hàm cv::gpu::multiply().

OpenCV và CUDA sẽ xử lý việc chia nhỏ và chia nhiệm vụ theo cách tốt nhất. Nói chung, mỗi đơn vị máy tính (ví dụ: lõi) trong GPU có thể chạy nhiều luồng (thường> = 16 trong CUDA). Điều này ngoài việc có thẻ có thể xuất hiện dưới dạng nhiều GPU hoặc đặt nhiều thẻ được liên kết trong cùng một máy.

Toàn bộ điểm cv::gpu là để giúp bạn không phải biết bất kỳ điều gì về cách thức hoạt động của nội bộ.

+0

Vâng, đúng vậy. Hàm multiply() được viết để tận dụng lợi thế của luồng CUDA trong chính hàm đó. Tuy nhiên, những gì tôi cần là nhiều hơn một hàm nhân() hoạt động trong các luồng song song. Điều đó dường như không thể có mà không có nhiều gpus. Sau đó, bạn có thể thực hiện một hàm multiply() trên mỗi song song và cho các hình ảnh khác nhau cùng một lúc. – mmccullo

+0

@mmccullo - yes cv :: gpu sử dụng luồng cuda cấp thấp, bạn có thể gọi nó trong nhiều chủ đề người dùng nhưng mỗi người sẽ sử dụng đầy đủ các gpu cho đến khi người kia kết thúc. Nếu bạn có một thẻ với cuda2 nó sẽ sử dụng suối để làm điều này async để chủ đề của bạn không chặn –

+0

Tôi đang sử dụng CUDA v4.2. Tôi không chắc chắn những gì bạn tham chiếu đến "cuda2" có nghĩa là chính xác. Nó dường như không nhất thiết phải chặn các chủ đề OpenMP của tôi, nhưng nó thời gian thực hiện mã của tôi ở trên chỉ tốt hơn một chút so với thực hiện trong một chủ đề duy nhất. Nó xuất hiện việc thực thi nhiều luồng xảy ra serially trên thiết bị CUDA đơn lẻ - nếu không thời gian thực hiện sẽ ít hơn nhiều so với chuỗi đơn trên cùng một thiết bị. GPU thử nghiệm của tôi là Quadro2000M với lõi 2GB và 192 CUDA. Hình ảnh có độ phân giải 1280x960 RGB. – mmccullo

0

Tôi không biết gì về chức năng GPU của OpenCV, nhưng nếu chúng hoàn toàn độc lập (ví dụ: tạo ngữ cảnh GPU, chuyển dữ liệu sang GPU, kết quả tính toán, chuyển kết quả về CPU), thì không có gì đáng ngạc nhiên các chức năng này xuất hiện theo thứ tự khi sử dụng một GPU duy nhất.

Nếu bạn có nhiều GPU, thì có một số cách để cho biết chức năng OpenCV nhắm mục tiêu một GPU cụ thể. Nếu bạn có nhiều GPU và có thể nhắm mục tiêu chúng hiệu quả, thì tôi không thấy lý do gì khiến các cuộc gọi hàm GPU sẽ không được song song. Theo wiki OpenCV, chức năng GPU chỉ nhắm mục tiêu một GPU duy nhất, nhưng bạn có thể tự chia nhỏ công việc: http://opencv.willowgarage.com/wiki/OpenCV%20GPU%20FAQ#Can_I_use_two_or_more_GPUs.3F

Các GPU kép như GTX 690 sẽ xuất hiện dưới dạng hai thiết bị riêng biệt với bộ nhớ riêng của chúng. chương trình là có liên quan. Xem ở đây: http://forums.nvidia.com/index.php?showtopic=231726

Ngoài ra, nếu bạn đang đi một con đường GPU kép cho các ứng dụng tính toán, tôi muốn giới thiệu với các GTX 690 vì hiệu suất tính toán của nó là hơi tê liệt so với GTX 590.

+0

Nhận xét thú vị về hiệu suất 690 so với 590. [NVidia page] (http://developer.nvidia.com/cuda-gpus) cho biết khả năng máy tính cao hơn cho 690. Bạn có bất kỳ chi tiết cụ thể nào về cách 690 bị tê liệt không? – mmccullo

+0

"Theo wiki OpenCV, chức năng GPU chỉ nhắm mục tiêu một GPU duy nhất, nhưng bạn có thể tự chia tay công việc" đáng buồn là liên kết không hoạt động. Nó có nghĩa là chia tay nó ra sao? Bạn phải đặt Id thiết bị trước mỗi cuộc gọi opencv gpu? Có bất kỳ ví dụ chính thức nào hỗ trợ tuyên bố hay không. – alap

+0

Cũng có nghĩa là trong chế độ SLI/CrossFire, bạn nên chuyển đổi thủ công? – alap

0

GTX 290 cư xử như 2 thiết bị CUDA riêng biệt, bất kể bạn sử dụng phiên bản OpenCV nào. Bạn không cần nhiều thẻ GPU để có được nhiều GPU, mà bạn có 2 trên một thẻ như trong GTX 290. Nhưng, từ quan điểm lập trình CUDA, không có nhiều khác biệt giữa việc sử dụng hai GPU trên 290 và sử dụng 2 GPU trên các thẻ GPU được kết nối riêng. Nhiều người dùng OpenCV sử dụng thư viện ArrayFire CUDA để bổ sung thêm nhiều tính năng xử lý hình ảnh và khả năng mở rộng đa GPU dễ dàng. Tất nhiên, sự từ chối của tôi là tôi làm việc trên ArrayFire, nhưng tôi thực sự nghĩ rằng nó sẽ giúp bạn trong trường hợp này.

4

Câu trả lời từ Martin đã làm việc cho tôi. Điều quan trọng là sử dụng gpu :: Stream class nếu thiết bị CUDA của bạn được liệt kê là khả năng tính toán 2 hoặc cao hơn. Tôi sẽ đặt nó ở đây bởi vì tôi không thể đăng đoạn mã một cách chính xác trong trình soạn thảo bình luận nhỏ.

cv::gpu::Stream stream[3]; 

for(int i=0; i<numImages; i++){ 
    for(int j=0; j<numChannels; j++){ 
     for(int k=0; k<pyramidDepth; k++){ 
      cv::gpu::multiply(pyramid[i][j][k], weightmap[i][k], pyramid[i][j][k], stream[i]); 
     } 
    } 
} 

Mã trên dường như thực thi phép nhân song song (numImages = 3 cho ứng dụng của tôi). Ngoài ra còn có các phương pháp Luồng để hỗ trợ tải lên/tải xuống hình ảnh đến và từ bộ nhớ GPU cũng như các phương pháp để kiểm tra trạng thái luồng để hỗ trợ đồng bộ hóa với mã khác.

Vì vậy ... dường như không yêu cầu nhiều thiết bị CUDA (ví dụ: thẻ GPU) để thực thi mã GPU OpenCV song song!

Các vấn đề liên quan