2012-06-29 15 views
8

मैं कंप्यूटर दृष्टि में किसी एप्लिकेशन के लिए ओपनसीवी का उपयोग कर रहा हूं। मैं जीपीयू पर कुछ मैट्रिक्स ऑपरेशंस (मैट्रिस काफी बड़े हैं) को तेज करना चाहता हूं और यदि संभव हो तो सीयूडीए सी में सीधे कोडिंग से बचना चाहता हूं। ओपनसीवी 2.4.1 में कई जीपीयू त्वरित कार्य हैं। वे आपके अनुभव में कितनी अच्छी तरह से प्रदर्शन करते हैं? क्या मैं इसके बजाय एक और लाइब्रेरी (उदाहरण के लिए जोर) का उपयोग बंद कर रहा हूँ?मैट्रिक्स परिचालनों के लिए ओपनसीवी जीपीयू लाइब्रेरी कितनी अच्छी है?

EDIT नमूना आवेदन: Calculate squared Euclidean distance matrix on GPU। वर्तमान में, समानांतर कंप्यूटिंग टूलबॉक्स (पीसीटी) का उपयोग करके मैटलैब में मेरा जीपीयू त्वरित (और वेक्टरकृत) कार्यान्वयन ओपनसीवी के साथ मेरे सी ++ कार्यान्वयन से लगभग 5-10 गुना तेज है।

मैटलैब कार्यान्वयन:

function K = sqEuclideanDist(P_cpu,Q_cpu) 
% Vectorized method to compute pairwise squared Euclidean distance on GPU 
% Returns K(i,j) = (P(i,:) - Q(j,:))'*(P(i,:) - Q(j,:)) 

P_gpu = gpuArray(P_cpu); 
Q_gpu = gpuArray(Q_cpu); 

[nP, d] = size(P_gpu); 
[nQ, d] = size(Q_gpu); 

pmag = sum(P_gpu .* P_gpu, 2); 
qmag = sum(Q_gpu .* Q_gpu, 2); 

% note that K is on GPU 
K = ones(nP,1)*qmag' + pmag*ones(1,nQ) - 2*P_gpu*Q_gpu'; 

end 

अद्यतन यहाँ एक और मैटलैब कार्यान्वयन कि (https://stackoverflow.com/a/7774323/1121420 करने के लिए धन्यवाद) एक ही पूरा करता है। लेकिन यह केवल सीपीयू पर चलता है क्योंकि bsxfun पीसीटी द्वारा समर्थित नहीं है। फिर भी सी ++ विकल्प की तलाश में है।

function K = sqEuclideanDist(P_cpu,Q_cpu) 
% Returns K(i,j) = (P(i,:) - Q(j,:))'*(P(i,:) - Q(j,:)) 
% Runs on CPU only. 

K = bsxfun(@plus,sum(p.^2,2),sum(q.^2,2)') - 2*(p*q'); 

end 
+0

विशेष रूप से क्या काम करता है आप का उपयोग पर विचार कर रहे हैं? –

+0

बेसिक मैट्रिक्स सामान। gpu :: कम करें, gpu :: गुणा करें (प्रति तत्व मैट्रिक्स गुणा)। इसके अलावा, मैट्रिक्स गुणा, मैट्रिक्स eigenvalues ​​और eigenvectors, मैट्रिक्स transpose खोज। – Alexey

+1

@Alex - सभी साधारण मैट्रिक्स ओप सीधे एनवीडिया (जोर?) लाइब्रेरी का उपयोग करते हैं, इसलिए बहुत अच्छी तरह से अनुकूलित –

उत्तर

3

मुझे ArrayFire बहुत तेज होने के लिए मिला है और छवि प्रसंस्करण के लिए ओपनसीवी में GPU कर्नेल के बजाय इसका उपयोग शुरू कर दिया है। यहां some benchmarks हैं जिन्हें मैंने ओरेसीएफवी में ऐरेफायर (लिबजैकेट नामक एक अलग इंटरफेस में इस्तेमाल किया) की तुलना में पाया और यह मेरे बेंचमार्किंग में भी सच रहा है कि ओरेसीएफ में जीपीयू कार्यों की तुलना में ऐरेफायर 2-4X तेज है। जो मैंने सुना है, एनवीआईडीआईए ने ओपनसीवी में जीपीयू कर्नेल नहीं लिखे थे, लेकिन उन लोगों को अनुबंधित किया, जो कि इतने धीमे हो सकते हैं। चूंकि मैं केवल 1 जीपीयू का उपयोग कर रहा हूं, इसलिए मैं ऐरेफ़ीयर का मुफ्त में उपयोग कर सकता हूं।

अद्यतन, @Alex: द्वारा पोस्ट किए गए नए MATLAB कोड को देखते हुए मैंने अपने सिस्टम पर इस कोड का बेंचमार्क चलाया। मुझे लगता है कि समांतर कंप्यूटिंग टूलबॉक्स gpuArray CPU से धीमा है, लेकिन जैकेट और ArrayFire किक बट। HW चश्मा हैं:

CPU के
Intel(R) Xeon(R) CPU X5660 @ 2.80GHz 
NVIDIA Tesla M2090 

परिणाम पैरलल कंप्यूटिंग उपकरण बॉक्स gpuArray (पूरी तरह से गरम) का उपयोग कर GPU बनाम। सीपीयू पीसीटी gpuArray की तुलना में तेजी है: जैकेट (पूरी तरह से गरम) का उपयोग कर सीपीयू GPU बनाम की

>> tic; sqEuclideanDist(gpuArray(rand(1581,3)),gpuArray(rand(189,3))); toc; 
Elapsed time is 0.006859 seconds. 
>> tic; sqEuclideanDist(rand(1581,3),rand(189,3)); toc; 
Elapsed time is 0.005712 seconds. 

परिणाम। जैकेट पीसीटी gpuArray 3 द्वारा धड़कता है।7X और 3X

>> tic; sqEuclideanDist(gdouble(rand(1581,3)),gdouble(rand(189,3))); toc; 
Elapsed time is 0.001876 seconds. 

यहाँ से सीपीयू धड़कता संशोधित कोड है कि है कि आसानी से आप चलाने के सभी है:

function K = sqEuclideanDist(P,Q) 
% Vectorized method to compute pairwise squared Euclidean distance on GPU 
% Returns K(i,j) = (P(i,:) - Q(j,:))'*(P(i,:) - Q(j,:)) 

[nP, d] = size(P); 
[nQ, d] = size(Q); 

pmag = sum(P .* P, 2); 
qmag = sum(Q .* Q, 2); 

K = ones(nP,1)*qmag' + pmag*ones(1,nQ) - 2*P*Q'; 

end 

जैकेट GPU पर समर्थन BSXFUN करता है, और यह कुछ हद तक गति में सुधार करता है :

>> tic; sqEuclideanDist(gdouble(rand(1581,3)),gdouble(rand(189,3))); toc; 
Elapsed time is 0.001420 seconds. 

ध्यान दें कि आकार यहां इस्तेमाल किया, बहुत छोटे हैं, इसलिए अधिकांश CUDA कोड है कि इन छोटे आकार पर चलाने के लिए प्रयास करता है खराब प्रदर्शन की संभावना है। यही कारण है कि मैं एक्सेलेरियस की सामग्री का उपयोग करना पसंद करता हूं, क्योंकि उन लोगों ने पीपीटी जीपीयूएरे, थ्रस्ट, ओपनसीवी के विपरीत जीपीयू से बिल्ली को अनुकूलित किया है, जिनमें से प्रत्येक मैंने अतीत में कोशिश की है।

यहाँ ArrayFire नि: शुल्क सी ++ परिणाम है:

Time: 0.0003577 seconds 
Speedups: 19.2X faster than PCT gpuArray, 16X faster than the CPU, 5.2X faster 
than Jacket in MATLAB original version, 4X faster than Jacket in MATLAB using 
BSXFUN 

यहाँ ArrayFire कोड मैं इस के लिए लिखा था है:

static array SqEuclideanDist(array P, array Q) 
{ 
    // 0 based indexing 
    array pmag = sum(P * P, 1); 
    array qmag = sum(Q * Q, 1); 

    int np = P.dims(0); 
    int nq = Q.dims(0); 

    array K = tile(qmag.T(), np, 1) * tile(pmag, 1, nq) - 2 * matmul(P, Q.T()); 
    return K; 
} 

int main(int argc, char **argv) 
{ 
    double *P_cpu = new double[1581 * 3]; 
    double *Q_cpu = new double[189 * 3]; 

    array P = array(1581, 3, P_cpu); 
    array Q = array(189 , 3, Q_cpu); 
    af::sync(); 

    int iter = 1000; 

    timer::tic(); 
    for (int i = 0; i < iter; i++) { 
     array K = SqEuclideanDist(P, Q); 
     af::eval(K); 
    } 

    af::sync(); 
    printf("Time taken: %2.4lfms\n", (1000 * timer::toc())/iter); 

    delete[] P_cpu; 
    delete[] Q_cpu; 
} 
+1

महान काम। विकल्प प्रदान करने के लिए धन्यवाद। निश्चित रूप से आज कुछ सीख लिया: bsxfun के लिए जैकेट के समर्थन के बारे में नहीं पता था और मुझे ArrayFire का सरल कोड पसंद है। केवल एक चीज है - भले ही ArrayFire C++ लाइब्रेरी का एक मुफ्त संस्करण है, मुफ्त संस्करण बहुत सीमित कार्यक्षमता प्रदान करता है (उदाहरण के लिए यह रैखिक बीजगणित संचालन का समर्थन नहीं करता है)। मैं एक ओपन सोर्स लाइब्रेरी की तलाश में हूं, क्या आप कोई सुझाव दे सकते हैं? – Alexey

+0

आपका स्वागत है। आश्चर्य की बात है कि इस पोस्ट को कितने लोगों ने कम किया। शायद MathWorks कर्मचारी। –

+0

दुर्भाग्यवश एक ओपन सोर्स लाइब्रेरी नहीं है जो बहुत अच्छा प्रदर्शन देती है। यही कारण है कि मैं ArrayFire का उपयोग कर रहा हूं, कम से कम यह मेरी आवश्यकता के लिए स्वतंत्र है। ArrayFire में बहुत अधिक फ़ंक्शन मुफ़्त है, जो CULA से आते हैं, जो रैखिक बीजगणित सामग्री के लिए मैग्मा से बेहतर है। लेकिन ऐरेफ़ीयर में नि: शुल्क एकल-परिशुद्धता रैखिक बीजगणित कार्य होता है, जिसका मैं अक्सर उपयोग करता हूं। क्या वह काम तुम्हारे लिये होगा? बीटीडब्लू, आपके द्वारा पोस्ट किया गया कोड उन रैखिक बीजगणित सुविधाओं का उपयोग नहीं करता है। –

1

उन्हें एनवीडिया द्वारा योगदान दिया गया है, इसलिए सीयूडीए संगत कार्ड पर अच्छा प्रदर्शन है। वास्तविक प्रदर्शन कार्ड और स्वयं जिस फ़ंक्शन का उपयोग कर रहे हैं उस पर निर्भर करता है।

मेरे अनुभव में केवल सामान्य इंटेल सीपीयू की तुलना में सीवीआरोटेट और सीवीआरसाइज का बेहतर प्रदर्शन था। (नोट: मुझे केवल छवि संबंधित कार्यों में दिलचस्पी थी)

संबंधित मुद्दे