2012-11-09 7 views
40

मैं लगभग 10 युक्त एक सांख्यिकीय आवेदन पर काम कर रहा हूँ।क्या मैं इस कोड को जीपीयू पर चला सकता/सकती हूं? 30 लाख से एक सरणी में चल बिन्दु मान -

कई तरीकों, नेस्टेड छोरों में सरणी पर अलग अलग है, लेकिन स्वतंत्र, गणना प्रदर्शन उदाहरण के लिए:

Dictionary<float, int> noOfNumbers = new Dictionary<float, int>(); 

for (float x = 0f; x < 100f; x += 0.0001f) { 
    int noOfOccurrences = 0; 

    foreach (float y in largeFloatingPointArray) { 
     if (x == y) { 
      noOfOccurrences++; 
     } 
    } 

    noOfNumbers.Add(x, noOfOccurrences); 
} 

वर्तमान आवेदन सी ​​# में लिखा है, एक इंटेल सीपीयू पर चलता है और कई घंटे की जरूरत को पूरा करने के। मैं GPU प्रोग्रामिंग अवधारणाओं और एपीआई का ज्ञान नहीं है, तो मेरे सवालों हैं:

  • क्या यह संभव है (और यह समझ पड़ता है) इस तरह के गणना में तेजी लाने के लिए एक GPU का उपयोग करने की?
  • यदि हाँ: किसी को भी किसी भी ट्यूटोरियल पता या किसी नमूना कोड (प्रोग्रामिंग भाषा कोई फर्क नहीं पड़ता) मिल गया है?

किसी भी मदद अत्यधिक सराहना की जाएगी।

+2

कोई मौका करके, आप C/C++ में अपने कोड में परिवर्तित करने की कोशिश की है? नीचे दिए गए कोड स्निपेट के आधार पर, आप सी # का उपयोग कर रहे हैं। यदि आपका कोड शब्दकोश के लिए स्मृति आवंटित करने में अपना अधिकांश समय बिताता है तो मुझे आश्चर्य नहीं होगा। – Martin

+3

नहीं, लेकिन शब्दकोश के लिए स्मृति आवंटित करने में केवल कुछ एमएस या उससे कम समय लगता है और CPU उपयोग हमेशा 93% - 98% के बीच होता है, इसलिए मुझे लगता है कि स्मृति इस मामले में (मुख्य) प्रदर्शन समस्या नहीं है। – Mike

+4

मुझे सच में लगता है कि आपका कोड GPU का उपयोग किये बिना तेजी से चमक रहा होना चाहिए। क्या आपने एक शब्दकोश का उपयोग करने से दूर जाने की कोशिश की है (सब कुछ आवंटित करें)। Foreach का उपयोग न करें लेकिन के लिए। जीपीयू अधिक है। सी में पूरी चीज दोबारा लिखें, यह आपको स्मृति आवंटन के बारे में सोचने के लिए मजबूर करेगा। – Martin

उत्तर

76

अद्यतन GPU संस्करण

__global__ void hash (float *largeFloatingPointArray,int largeFloatingPointArraySize, int *dictionary, int size, int num_blocks) 
{ 
    int x = (threadIdx.x + blockIdx.x * blockDim.x); // Each thread of each block will 
    float y;           // compute one (or more) floats 
    int noOfOccurrences = 0; 
    int a; 

    while(x < size)   // While there is work to do each thread will: 
    { 
     dictionary[x] = 0;  // Initialize the position in each it will work 
     noOfOccurrences = 0;  

     for(int j = 0 ;j < largeFloatingPointArraySize; j ++) // Search for floats 
     {              // that are equal 
                  // to it assign float 
      y = largeFloatingPointArray[j]; // Take a candidate from the floats array 
      y *= 10000;      // e.g if y = 0.0001f; 
      a = y + 0.5;      // a = 1 + 0.5 = 1; 
      if (a == x) noOfOccurrences++;  
     }          

     dictionary[x] += noOfOccurrences; // Update in the dictionary 
              // the number of times that the float appears 

    x += blockDim.x * gridDim.x; // Update the position here the thread will work 
    } 
} 

यह एक मैं सिर्फ छोटे आदानों के लिए परीक्षण किया है, क्योंकि मैं मैं अपने लैपटॉप का परीक्षण कर रहा हूँ। फिर भी, यह काम किया। हालांकि, आगे परीक्षण टेस्ट करना आवश्यक है।

अद्यतन अनुक्रमिक संस्करण

मैं सिर्फ इस अनुभवहीन संस्करण है कि कम से कम 20 सेकंड (पहले से ही डेटा उत्पन्न करने के लिए समारोह की गिनती) में 30,000,000 के लिए अपने एल्गोरिथ्म प्रदर्शन किया।

असल में, यह आपके फ्लोट की सरणी को सॉर्ट करता है। यह क्रमबद्ध सरणी पर यात्रा करेगा, यह मानने के लिए कि सरणी में लगातार मूल्य कितनी बार दिखाई देता है और फिर यह मान एक शब्दकोश में प्रदर्शित होने की संख्या के साथ एक शब्द में डाल देता है।

आप इस्तेमाल किए गए unordered_map के बजाय क्रमबद्ध मानचित्र का उपयोग कर सकते हैं।

यहाँ कोड:

#include <stdio.h> 
#include <stdlib.h> 
#include "cuda.h" 
#include <algorithm> 
#include <string> 
#include <iostream> 
#include <tr1/unordered_map> 


typedef std::tr1::unordered_map<float, int> Mymap; 


void generator(float *data, long int size) 
{ 
    float LO = 0.0; 
    float HI = 100.0; 

    for(long int i = 0; i < size; i++) 
     data[i] = LO + (float)rand()/((float)RAND_MAX/(HI-LO)); 
} 

void print_array(float *data, long int size) 
{ 

    for(long int i = 2; i < size; i++) 
     printf("%f\n",data[i]); 

} 

std::tr1::unordered_map<float, int> fill_dict(float *data, int size) 
{ 
    float previous = data[0]; 
    int count = 1; 
    std::tr1::unordered_map<float, int> dict; 

    for(long int i = 1; i < size; i++) 
    { 
     if(previous == data[i]) 
      count++; 
     else 
     { 
      dict.insert(Mymap::value_type(previous,count)); 
      previous = data[i]; 
      count = 1;   
     } 

    } 
    dict.insert(Mymap::value_type(previous,count)); // add the last member 
    return dict; 

} 

void printMAP(std::tr1::unordered_map<float, int> dict) 
{ 
    for(std::tr1::unordered_map<float, int>::iterator i = dict.begin(); i != dict.end(); i++) 
    { 
    std::cout << "key(string): " << i->first << ", value(int): " << i->second << std::endl; 
    } 
} 


int main(int argc, char** argv) 
{ 
    int size = 1000000; 
    if(argc > 1) size = atoi(argv[1]); 
    printf("Size = %d",size); 

    float data[size]; 
    using namespace __gnu_cxx; 

    std::tr1::unordered_map<float, int> dict; 

    generator(data,size); 

    sort(data, data + size); 
    dict = fill_dict(data,size); 

    return 0; 
} 

आप पुस्तकालय जोर आप मशीन में स्थापित है, तो आप इस का उपयोग करना चाहिए: सुनिश्चित करें कि के लिए

#include <thrust/sort.h> 
thrust::sort(data, data + size); 
इस

sort(data, data + size); 

के बजाय

यह तेजी से होगा।

मूल पोस्ट

"मैं जो 10 containin एक बड़े सरणी है एक सांख्यिकीय आवेदन पर काम कर रहा हूँ - अंक मान चल के 30 लाखों लोगों की"।

"क्या ऐसी गणनाओं को तेज करने के लिए जीपीयू का उपयोग करने के लिए यह संभव है (और यह समझ में आता है)?"

हाँ, यह है। एक महीने पहले मैंने पूरी तरह से जीपीयू पर आण्विक गतिशील सिमुलेशन लगाया था। कणों में से एक, जो कणों के जोड़ों के बीच बल की गणना करता है, 500,000 युगल के साथ प्रत्येक 6 सरणी प्राप्त करता है, कुल 3 मिलियन युगल (22 एमबी)।

तो आप 30 मिलियन फ्लोट प्वाइंट डालने की योजना बना रहे हैं, यह लगभग 114 एमबी वैश्विक मेमोरी है, इसलिए यह कोई समस्या नहीं है, यहां तक ​​कि मेरे लैपटॉप में 250 एमबी भी है।

गणना आपके मामले में कोई समस्या हो सकती है? आण्विक गतिशील (एमडी) के साथ अपने अनुभव के आधार पर मैं नहीं कहता हूं। अनुक्रमिक एमडी संस्करण को पूरा होने में लगभग 25 घंटे लगते हैं जबकि GPU में 45 मिनट लगते हैं। आपने कहा कि आपके आवेदन में कुछ घंटे लगे हैं, जो आपके कोड उदाहरण में भी आधारित है, यह आण्विक गतिशील से नरम दिखता है।

ग में:

for(int i = 0; i < N; i++) 
    c[i] = a[i] + b[i]; 

Cuda में

__global__ void add(double *fx, double *fy, double *fz, 
        double *x, double *y, double *z,...){ 

    int pos = (threadIdx.x + blockIdx.x * blockDim.x); 

    ... 

    while(pos < particles) 
    { 

     for (i = 0; i < particles; i++) 
     { 
       if(//inside of the same radius) 
       { 
       // calculate force 
       } 
     } 
    pos += blockDim.x * gridDim.x; 
    }   
    } 

Cuda में एक कोड का एक सरल उदाहरण दो 2 डी सरणियों का योग हो सकता है:

यहाँ बल गणना उदाहरण है :

__global__ add(int *c, int *a, int*b, int N) 
{ 
    int pos = (threadIdx.x + blockIdx.x) 
    for(; i < N; pos +=blockDim.x) 
     c[pos] = a[pos] + b[pos]; 
} 

Cuda में आप मूल रूप से प्रत्येक थ्रेड द्वारा यात्रा और भाग के लिए प्रत्येक ले लिया,

1) threadIdx.x + blockIdx.x*blockDim.x; 

प्रत्येक ब्लॉक 0 से N-1 के लिए एक आईडी (एन ब्लॉक की संख्या अधिकतम) है और प्रत्येक ब्लॉक धागे की एक एक्स नंबर है 0 से एक्स -1 तक आईडी के साथ।

1) आपको पुनरावृत्ति के लिए देता है कि प्रत्येक थ्रेड उस आईडी और ब्लॉक आईडी पर आधारित गणना करेगा जहां थ्रेड है, blockDim.x एक ब्लॉक है जो थ्रेड की संख्या है।

तो अगर आप 2 ब्लॉक 10 धागे से हर एक है और एक एन = 40, है:

__global__ hash (float *largeFloatingPointArray, int *dictionary) 
    // You can turn the dictionary in one array of int 
    // here each position will represent the float 
    // Since x = 0f; x < 100f; x += 0.0001f 
    // you can associate each x to different position 
    // in the dictionary: 

    // pos 0 have the same meaning as 0f; 
    // pos 1 means float 0.0001f 
    // pos 2 means float 0.0002f ect. 
    // Then you use the int of each position 
    // to count how many times that "float" had appeared 


    int x = blockIdx.x; // Each block will take a different x to work 
    float y; 

while(x < 1000000) // x < 100f (for incremental step of 0.0001f) 
{ 
    int noOfOccurrences = 0; 
    float z = converting_int_to_float(x); // This function will convert the x to the 
              // float like you use (x/0.0001) 

    // each thread of each block 
    // will takes the y from the array of largeFloatingPointArray 

    for(j = threadIdx.x; j < largeFloatingPointArraySize; j += blockDim.x) 
    { 
     y = largeFloatingPointArray[j]; 
     if (z == y) 
     { 
      noOfOccurrences++; 
     } 
    } 
    if(threadIdx.x == 0) // Thread master will update the values 
     atomicAdd(&dictionary[x], noOfOccurrences); 
    __syncthreads(); 
} 
: मैं क्या यह CUDA में हो सकता है की इस मसौदा बनाया

Thread 0 Block 0 will execute pos 0 
Thread 1 Block 0 will execute pos 1 
... 
Thread 9 Block 0 will execute pos 9 
Thread 0 Block 1 will execute pos 10 
.... 
Thread 9 Block 1 will execute pos 19 
Thread 0 Block 0 will execute pos 20 
... 
Thread 0 Block 1 will execute pos 30 
Thread 9 Block 1 will execute pos 39 

अपने कोड को खोज रहे हैं

आपको परमाणु का उपयोग करना है क्योंकि अलग-अलग ब्लॉक से अलग-अलग थ्रेड एक ही समय में नहीं लिख सकते हैं, इसलिए आपको पारस्परिक बहिष्करण अनिश्चित करना होगा।

यह केवल एक ही दृष्टिकोण है जिसे आप ब्लॉक के बजाय बाहरी लूप के पुनरावृत्तियों को भी दे सकते हैं।

ट्यूटोरियल

रोब किसान द्वारा डॉ डोब्स जर्नल श्रृंखला CUDA: Supercomputing for the masses उत्कृष्ट है और सिर्फ अपनी चौदह किश्तों में सब कुछ के बारे में शामिल किया गया। यह बल्कि धीरे-धीरे शुरू होता है और इसलिए काफी शुरुआती-अनुकूल है।

और दूसरे:

अंतिम आइटम पर एक नजर डालें, तो आप CUDA जानने के लिए कई लिंक मिल जाएगा।

OpenCL: OpenCL Tutorials | MacResearch

+13

अब यह एक प्रकार का उत्तर है जिसके लिए मैं SO में शामिल हो गया ... Kudos! – DarkWanderer

+6

ठीक है, मैं क्या कह सकता हूं, यह अब तक का सबसे अच्छा जवाब है जो मुझे एसओ पर मिला है। आप प्रतिभाशाली व्यक्ति हैं, धन्यवाद और: vielen डंक! :-) ओपनसीएल और एएमडी अति के बारे में क्या, क्या आपको इस संयोजन के साथ अनुभव है, आपकी राय क्या है? – Mike

+6

बहुत बहुत धन्यवाद, यहां निश्चित रूप से उच्च गुणवत्ता वाले उत्तर हैं। मैंने ओपनसीएल को ईमानदार होने की कोशिश नहीं की थी, मैं सिर्फ क्यूडा और एनवीआईडीआईए डिवाइस (जैसे टेस्ला सी 2050) के साथ काम करता हूं, क्योंकि यह मेरे काम में क्लस्टर में उपलब्ध है :)। – dreamcrash

11

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

इसके अलावा, आप वास्तव में नहीं बार-बार ऐसे ही एक चल बिन्दु संख्या के लिए एक छोटी राशि जोड़ना चाहते हैं, गोलाई त्रुटि को जोड़ देंगे और आप आप क्या इरादा नहीं मिलेगा। मैंने नीचे दिए गए नमूने में एक कथन जोड़ा है ताकि यह जांच सके कि इनपुट आपके पुनरावृत्ति के पैटर्न से मेल खाता है या नहीं, लेकिन अगर आपको वास्तव में इसकी आवश्यकता नहीं है तो इसे छोड़ दें।

मैं किसी भी सी # पता नहीं है, लेकिन अपने नमूने के एक भी पास कार्यान्वयन कुछ इस तरह दिखेगा:

Dictionary<float, int> noOfNumbers = new Dictionary<float, int>(); 

foreach (float x in largeFloatingPointArray) 
{ 
    if (math.Truncate(x/0.0001f)*0.0001f == x) 
    { 
     if (noOfNumbers.ContainsKey(x)) 
      noOfNumbers.Add(x, noOfNumbers[x]+1); 
     else 
      noOfNumbers.Add(x, 1); 
    } 
} 

आशा इस मदद करता है।

+4

आप ContainsKey के बजाय TryGet का उपयोग करके और फिर NoOfNumbers [x] का उपयोग करके अपना कोड सुधार सकते हैं। TryGet का उपयोग करके आपको एक शब्दकोश लुकअप बचाता है, जो ओ (1) amortized है (यानी हमेशा ओ (1) नहीं) और एक महंगा ओ (1) है क्योंकि एक शब्दकोश एक जटिल डेटा प्रकार है। वैसे भी +1 –

+3

आपकी मदद के लिए धन्यवाद। इसकी बहुत सराहना की जाती है और आपके सुझाव जल्द ही मेरे आवेदन में जोड़े जाएंगे। दुर्भाग्यवश मेरे पास लगभग 100 अन्य विधियां हैं जो मुझे लगता है कि अधिक अनुकूलित नहीं किया जा सकता है। यहां तक ​​कि यदि मैं कोड अनुकूलन का उपयोग करके 90% तक इस तरह की गणना को तेज करने के लिए प्राप्त करता हूं, तो इसे अभी भी तेज CPU पर पूरा होने में कई घंटे लग सकते हैं। – Mike

+3

कृपया हमें सीमित डेटासेट (और अपना स्वयं का बेंचमार्क) के साथ पूर्ण विधि भेजें। इससे हमें आपकी बहुत मदद करने की क्षमता मिल जाएगी। अब तक आपके कोड में जो कुछ भी देख रहा हूं, उसके आधार पर, मुझे पूरा यकीन है कि मैं GPU का उपयोग शुरू करने से पहले कोड की गति को दोगुना कर सकता हूं। – Martin

6

उपरोक्त पोस्टर द्वारा दिए गए सुझाव के अलावा एकाधिक कोर पर समानांतर में चलाने के लिए उपयुक्त होने पर टीपीएल (कार्य समानांतर लाइब्रेरी) का उपयोग करें।

उपर्युक्त उदाहरण समानांतर। Foreach और ConcurrentDictionary का उपयोग कर सकता है, लेकिन एक अधिक जटिल मानचित्र-सेटअप को कम करता है जहां सरणी को प्रत्येक शब्दकोष उत्पन्न करने वाले हिस्सों में विभाजित किया जाता है जिसे एक सिंगल डिक्शनरी में कम किया जाएगा जिससे आपको बेहतर परिणाम मिलेंगे।

मुझे नहीं पता कि आपके सभी कंप्यूटेशंस जीपीयू क्षमताओं के लिए सही तरीके से मानचित्र हैं या नहीं, लेकिन आपको जीपीयू कोर की गणना को मैप करने के लिए किसी भी तरह मैप-कम एल्गोरिदम का उपयोग करना होगा और फिर आंशिक परिणाम को एकल में कम करना होगा परिणाम, तो आप कम परिचित प्लेटफ़ॉर्म पर जाने से पहले CPU पर भी ऐसा कर सकते हैं।

+3

आपके सुझावों के लिए धन्यवाद। मैं पहले से ही टीपीएल का उपयोग कर रहा हूं लेकिन उच्च स्तर पर। इसका मतलब है कि मेरा ऐप कई तरीकों को समानांतर कहता है जो अच्छी तरह से काम करता है (सीपीयू उपयोग 90% से ऊपर)। – Mike

6

मुझे यकीन नहीं है कि जीपीयू का उपयोग करना एक अच्छा मैच होगा, 'bigFloatingPointArray' मानों को स्मृति से पुनर्प्राप्त करने की आवश्यकता है। मेरी समझ यह है कि जीपीयू स्वयं निहित गणनाओं के लिए बेहतर अनुकूल हैं।

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

आप क्लासिक 'विभाजन और जीत' दृष्टिकोण का उपयोग कर सकते हैं। मैं जो सामान्य दृष्टिकोण लेता हूं वह निम्नानुसार है।

एक हैश तालिका या डेटाबेस में 'bigFloatingPointArray' preprocess करने के लिए एक सिस्टम का उपयोग करें। यह एक ही पास में किया जाएगा। यह फ्लोटिंग पॉइंट वैल्यू को कुंजी के रूप में उपयोग करेगा, और सरणी में होने वाली घटनाओं की संख्या मान के रूप में होगी। सबसे खराब स्थिति यह है कि प्रत्येक मान केवल एक बार होता है, लेकिन यह असंभव है। यदि बड़े फ्लाइटिंगपॉइंटएरे प्रत्येक बार एप्लिकेशन चलाए जाने पर बदलता रहता है तो मेमोरी हैश टेबल समझ में आता है। यदि यह स्थैतिक है, तो तालिका को बर्कले डीबी जैसे कुंजी-मान डेटाबेस में सहेजा जा सकता है। आइए इसे 'लुकअप' सिस्टम कहते हैं।

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

प्रदर्शन में सुधार हुआ है क्योंकि हम bigFloatingPointArray पर पुन: प्रयास नहीं करते हैं। यदि लुकअप सिस्टम एक बाधा बन जाता है, तो इसे आवश्यकतानुसार कई प्रणालियों पर दोहराया जा सकता है।

समानांतर में काम कर रहे सिस्टम की बड़ी संख्या के साथ, प्रसंस्करण समय को मिनटों तक कम करना संभव होना चाहिए।

मैं कई कोर आधारित प्रणालियों के लिए लक्षित सी में समानांतर प्रोग्रामिंग के लिए एक कंपाइलर पर काम कर रहा हूं, जिसे अक्सर माइक्रोसेवर के रूप में जाना जाता है, जो/या कई 'सिस्टम-ऑन-ए-चिप' मॉड्यूल का उपयोग करके बनाया जाएगा प्रणाली। एआरएम मॉड्यूल विक्रेताओं में कैल्केडा, एएमडी, एएमसीसी, इत्यादि शामिल हैं। इंटेल की भी इसी तरह की पेशकश होगी।

मेरे पास कंपाइलर काम करने का एक संस्करण है, जिसका उपयोग इस तरह के एप्लिकेशन के लिए किया जा सकता है। सी फ़ंक्शन प्रोटोटाइप के आधार पर कंपाइलर, सी नेटवर्किंग कोड उत्पन्न करता है जो सिस्टम में इंटर-प्रोसेस संचार कोड (आईपीसी) लागू करता है। उपलब्ध आईपीसी तंत्र में से एक सॉकेट/टीसीपी/आईपी है।

यदि आपको एक वितरित समाधान को लागू करने में मदद की ज़रूरत है, तो मुझे आपके साथ चर्चा करने में खुशी होगी।

जोड़ा गया Nov 16, 2012

मैं थोड़ा एल्गोरिथ्म के बारे में अधिक सोचा और मुझे लगता है कि यह एक एकल पास में यह करना चाहिए। यह सी में लिखा गया है और यह आपके पास जो कुछ है उसके मुकाबले बहुत तेज़ होना चाहिए।

/* 
* Convert the X range from 0f to 100f in steps of 0.0001f 
* into a range of integers 0 to 1 + (100 * 10000) to use as an 
* index into an array. 
*/ 

#define X_MAX   (1 + (100 * 10000)) 

/* 
* Number of floats in largeFloatingPointArray needs to be defined 
* below to be whatever your value is. 
*/ 

#define LARGE_ARRAY_MAX (1000) 

main() 
{ 
    int j, y, *noOfOccurances; 
    float *largeFloatingPointArray; 

    /* 
    * Allocate memory for largeFloatingPointArray and populate it. 
    */ 

    largeFloatingPointArray = (float *)malloc(LARGE_ARRAY_MAX * sizeof(float));  
    if (largeFloatingPointArray == 0) { 
     printf("out of memory\n"); 
     exit(1); 
    } 

    /* 
    * Allocate memory to hold noOfOccurances. The index/10000 is the 
    * the floating point number. The contents is the count. 
    * 
    * E.g. noOfOccurances[12345] = 20, means 1.2345f occurs 20 times 
    * in largeFloatingPointArray. 
    */ 

    noOfOccurances = (int *)calloc(X_MAX, sizeof(int)); 
    if (noOfOccurances == 0) { 
     printf("out of memory\n"); 
     exit(1); 
    } 

    for (j = 0; j < LARGE_ARRAY_MAX; j++) { 
     y = (int)(largeFloatingPointArray[j] * 10000); 
     if (y >= 0 && y <= X_MAX) { 
      noOfOccurances[y]++; 
     } 
    } 
} 
+3

काम दूसरी बार मशीनों के नेटवर्क के बीच विभाजित किया जा सकता है; लेकिन GPU पावर का उपयोग करके सस्ते (और अक्सर विशाल) सुधार के लिए आईएमएचओ कहीं बेहतर है। आपके ढांचे के लिए यह एमपीआई से तुलना कैसे करता है? :) – Pragmateek

+0

सभी जानकारी और सी कोड के लिए धन्यवाद। शायद मुझे अपनी समस्या के लिए एक अच्छा समाधान मिला: http://bit.ly/Ta4aSL [पीडीएफ] बहुत आशाजनक लगता है ... आपको क्या लगता है? – Mike

+0

माइक, यह एक विशेष जीपीयू से बंधे बिना डायरेक्टएक्स का लाभ उठाने का एक दिलचस्प तरीका है। मैं साइड इफेक्ट्स, यदि कोई हो, के बारे में सोच रहा था। जबकि डायरेक्टएक्स का सक्रिय रूप से उपयोग किया जा रहा है, क्या प्रदर्शन के लिए ग्राफिक्स को प्रस्तुत करने वाले अन्य अनुप्रयोगों पर कोई प्रभाव पड़ता है? अपने ऐप के साथ और उसके बिना यूट्यूब या विंडोज मीडिया प्लेयर वीडियो चलाने का प्रयास करें और देखें कि क्या आपको वीडियो की गुणवत्ता में कोई गिरावट दिखाई दे रही है या नहीं। इसके अलावा, क्या आपको पता है कि भविष्य में आपको वर्कस्टेशन की क्षमता से परे स्केल करने की आवश्यकता हो सकती है? विंडोज वातावरण के अपने सभी हिस्से के बाद से, मुझे लगता है कि यह एक कोशिश के लायक है। –

8

क्या यह संभव है (और यह समझ बनाने करता है) ऐसी गणना तेजी लाने के लिए एक GPU का उपयोग करने की?

  • निश्चित रूप से हाँ, एल्गोरिथ्म इस तरह आम तौर पर बड़े पैमाने पर डेटा-समानांतरवाद प्रसंस्करण के लिए आदर्श उम्मीदवार हैं, बात GPUs पर बहुत अच्छे हैं।

यदि हाँ: किसी को भी किसी भी ट्यूटोरियल पता या किसी नमूना कोड (प्रोग्रामिंग भाषा कोई फर्क नहीं पड़ता) मिल गया है?CUDA या OpenCL:

  • आप GPGPU रास्ता तय करना चाहते हैं तो आपके पास दो विकल्प है।

    सीयूडीए बहुत सारे उपकरणों के साथ परिपक्व है लेकिन एनवीडिया जीपीयू केंद्रित है।

    ओपनसीएल एनवीडिया और एएमडी जीपीयू और सीपीयू पर भी मानक चल रहा है। तो आपको वास्तव में इसका पक्ष लेना चाहिए।

  • ट्यूटोरियल के लिए आप रोब फार्बर द्वारा CodeProject पर एक उत्कृष्ट श्रृंखला है: http://www.codeproject.com/Articles/Rob-Farber#Articles

  • अपने विशिष्ट यूज-केस के लिए वहाँ OpenCL साथ buiding हिस्टोग्राम के लिए नमूने का एक बहुत है (ध्यान दें कि कई छवि हिस्टोग्राम हैं लेकिन सिद्धांत समान हैं)।

  • आप उपयोग के रूप में सी # आप OpenCL.Net या Cloo तरह बाइंडिंग का उपयोग कर सकते हैं।

  • यदि आपका सरणी बहुत बड़ा GPU स्मृति में संग्रहित किया जा रहा है, आप ब्लॉक-विभाजन कर सकते हैं यह और आसानी से प्रत्येक भाग के लिए अपनी OpenCL गिरी पुनः चलाएं।

+2

कुशल हिस्टोग्राम algos पर एक अतिरिक्त संसाधन ... http://users.cecs.anu.edu.au/~ramtin/cuda.htm – kineticfocus

+2

आपकी मदद के लिए धन्यवाद! बहुत सराहना की। डायरेक्टएक्स पर आपकी क्या राय है? सी # www.sharpdx.org – Mike

+2

के लिए एक अच्छा एसडीके लगता है कुछ अतिरिक्त शोध किया। ओपनसीएल बहुत रोचक है क्योंकि यह ज़ीओन फाई और आधुनिक इंटेल सीपीयू के एकीकृत जीपीयू का भी समर्थन करता है, यहां देखें http://bit.ly/Ta29ab – Mike

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