GPU

2012-04-04 27 views
6

पर समन्वय परिवर्तन को ऑफ़लोड करना मेरे पास WinForms का उपयोग करके एक विरासत मानचित्र दर्शक एप्लिकेशन है। यह sloooooow है। (गति स्वीकार्य होती थी, लेकिन Google मानचित्र, Google धरती साथ आया और उपयोगकर्ता खराब हो गए। अब मुझे तेजी से बनाने की अनुमति है :)GPU

सभी स्पष्ट गति सुधार करने के बाद (कैशिंग, समांतर निष्पादन, ड्राइंग नहीं क्या तैयार करने की आवश्यकता नहीं है, आदि), मेरा प्रोफाइलर मुझे दिखाता है कि असली चोकिंग पॉइंट समन्वय परिवर्तन है जब मैप-स्पेस से स्क्रीन-स्पेस में अंक परिवर्तित करते हैं। आम तौर पर रूपांतरण कोड इस तरह दिखता है:

public Point MapToScreen(PointF input) 
    { 
     // Note that North is negative! 
     var result = new Point(
      (int)((input.X - this.currentView.X) * this.Scale), 
      (int)((input.Y - this.currentView.Y) * this.Scale)); 
     return result; 
    } 

वास्तविक कार्यान्वयन जटिल काम है। अक्षांश/अक्षांश पूर्णांक के रूप में दर्शाए जाते हैं। सटीकता को खोने से बचने के लिए, उन्हें 2^20 (~ 1 मिलियन) से गुणा किया जाता है। इस तरह एक समन्वय का प्रतिनिधित्व किया जाता है।

public struct Position 
{ 
    public const int PrecisionCompensationPower = 20; 
    public const int PrecisionCompensationScale = 1048576; // 2^20 
    public readonly int LatitudeInt; // North is negative! 
    public readonly int LongitudeInt; 
} 

यह महत्वपूर्ण है कि संभव पैमाने कारकों को भी स्पष्ट रूप से 2. की शक्ति के लिए बाध्य कर रहे हैं यह एक bitshift साथ गुणन को बदलने के लिए अनुमति देता है। तो असली एल्गोरिथ्म इस तरह दिखता है:

public Point MapToScreen(Position input) 
    { 
     Point result = new Point(); 
     result.X = (input.LongitudeInt - this.UpperLeftPosition.LongitudeInt) >> 
        (Position.PrecisionCompensationPower - this.ZoomLevel); 
     result.Y = (input.LatitudeInt - this.UpperLeftPosition.LatitudeInt) >> 
        (Position.PrecisionCompensationPower - this.ZoomLevel); 
     return result; 
    } 

(UpperLeftPosition नक्शा अंतरिक्ष में स्क्रीन के ऊपरी-बाएं कोने representents।) मैं GPU को यह गणना उतारने का अब सोच रहा हूँ। क्या कोई मुझे एक उदाहरण दिखा सकता है कि यह कैसे करें?

हम .NET4.0 का उपयोग करते हैं, लेकिन कोड को प्राथमिक रूप से विंडोज एक्सपी पर भी चलाना चाहिए। इसके अलावा, जीपीएल के तहत पुस्तकालय हम उपयोग नहीं कर सकते हैं।

उत्तर

1

अब एक साल बाद समस्या फिर से उभरी, और हमें बहुत ही कम जवाब मिला। मैं थोड़ा बेवकूफ महसूस कर रहा हूँ इसे पहले महसूस नहीं कर रहा हूँ। हम भौगोलिक तत्वों को सामान्य WinForms जीडीआई के माध्यम से बिटमैप में खींचते हैं। जीडीआई हार्डवेयर तेज है। हमें बस इतना करना है कि खुद को परिवर्तन न करें, लेकिन सिस्टम के स्केल पैरामीटर सेट करें। ड्रॉइंग.ग्राफिक्स ऑब्जेक्ट: ग्राफिक्स। ट्रांसस्लेट ट्रान्सफॉर्म (...) और ग्राफिक्स। स्केलट्रांसफॉर्म (...) हम नहीं करते हैं बिट स्थानांतरण के साथ भी चाल की जरूरत है।

:)

2

मैं सुझाव है कि आप ऐसा करते हैं करने के लिए OpenCL और Cloo का उपयोग कर देखो - करने के लिए vector add example पर एक नज़र डालें और फिर इसे बदल दो ComputeBuffer रों (प्रत्येक बिंदु में LongitudeIntLatitudeInt से प्रत्येक और के लिए एक) का उपयोग करके मान मैप करने के 2 आउटपुट ComputeBuffer एस। मुझे लगता है OpenCL कोड कुछ इस तरह दिखता होगा:

__kernel void CoordTrans(__global int *lat, 
         __global int *lon, 
         __constant int ulpLat, 
         __constant int ulpLon, 
         __constant int zl, 
         __global int *outx, 
         __global int *outy) 
{ 
    int i = get_global_id(0);   
    const int pcp = 20; 

    outx[i] = (lon[i] - ulpLon) >> (pcp - zl); 
    outy[i] = (lat[i] - ulpLat) >> (pcp - zl); 
} 

लेकिन आप मूल प्रति एक से अधिक coord-परिणत करना होगा। मुझे भागने की जरूरत है, मैं आपको ऐसा करने से पहले ओपनक्ल पर पढ़ने की सलाह देता हूं।

इसके अलावा, यदि कॉर्ड की संख्या उचित है (< 100,000/1,000,000) गैर-जीपीयू आधारित समाधान संभवतः तेज़ होगा।

1

मैं एक सीयूडीए पृष्ठभूमि से आ रहा हूं, और केवल एनवीआईडीआईए जीपीयू के लिए बात कर सकता हूं, लेकिन यहां जाता है।

GPU पर ऐसा करने में समस्या आपके ऑपरेशन/स्थानांतरण समय है।

आपके पास प्रति तत्व करने के लिए 1 ऑपरेशन के आदेश पर है। असली गति सुधार प्राप्त करने के लिए आप वास्तव में इस तत्व से अधिक करना चाहते हैं। ग्लोबल मेमोरी और जीपीयू पर धागे के बीच बैंडविड्थ लगभग 100 जीबी/एस है। इसलिए, यदि आपको एक एफएलओपी करने के लिए एक 4 बाइट पूर्णांक लोड करना है, तो आप सैद्धांतिक अधिकतम गति 100/4 = 25 फ़्लॉप्स हैं। यह विज्ञापित सैकड़ों फ्लॉप से ​​बहुत दूर है।

नोट यह सैद्धांतिक अधिकतम है, वास्तविक परिणाम खराब हो सकता है। और यदि आप एक से अधिक तत्व लोड कर रहे हैं तो यह भी बदतर है। आपके मामले में, यह 2 जैसा दिखता है, इसलिए आपको इससे अधिकतम 12.5 फ़्लॉप मिल सकते हैं। अभ्यास में, यह लगभग निश्चित रूप से कम होगा।

यदि यह आपके लिए ठीक लगता है, तो इसके लिए जाएं!

+0

+1 सैद्धांतिक सीमाओं को दिखाने के लिए +1। – user256890

+0

बस संख्याओं को परिप्रेक्ष्य में रखने के लिए, एफएलओपी में औसत 2 कोर सीपीयू की अनुमानित गति क्या है? – user256890

+0

यह उस पर निर्भर करता है जिसे आप फ़्लॉप कहते हैं। मान लीजिए कि आपके 2 कोर सीपीयू में 2 गीगाहर्ट्ज की घड़ी की गति है, और एक एफएलओपी 4 घड़ी चक्र लेता है। आप 2 * 2/4 = 1 जीएफएलओपी कर सकते हैं। यह एक बहुत ही कच्चा अनुमान है। –

1

एक्सएनए का उपयोग आपके द्वारा आवश्यक सभी परिवर्तनों को करने के लिए किया जा सकता है और बहुत अच्छा प्रदर्शन देता है। इसे Winforms एप्लिकेशन के अंदर भी प्रदर्शित किया जा सकता है: http://create.msdn.com/en-US/education/catalog/sample/winforms_series_1