2008-11-18 14 views
17

में डिवाइस मेमोरी आवंटन लपेटना मैं इस समय CUDA का उपयोग करना शुरू कर रहा हूं और मुझे यह स्वीकार करना होगा कि मैं सी एपीआई से थोड़ा निराश हूं। मैं सी चुनने के कारणों को समझता हूं लेकिन भाषा सी ++ पर आधारित थी, कई पहलुओं को बहुत आसान बना दिया गया था, उदाहरण के लिए डिवाइस मेमोरी आवंटन (cudaMalloc के माध्यम से)।CUDA: C++

मेरी योजना प्लेसमेंट new और आरएआईआई (दो विकल्प) के साथ अधिभारित operator new का उपयोग करके स्वयं को करना था। मैं सोच रहा हूं कि क्या ऐसी कोई चेतावनी है जो मैंने अभी तक नहीं देखी है। कोड काम करने के लिए लगता है लेकिन मैं अभी भी संभावित मेमोरी लीक के बारे में सोच रहा हूं।

आरए II कोड के उपयोग के रूप में निम्नानुसार होगा:

CudaArray<float> device_data(SIZE); 
// Use `device_data` as if it were a raw pointer. 

शायद एक वर्ग इस संदर्भ में overkill है (खासकर जब से तुम अब भी cudaMemcpy उपयोग करने के लिए होगा, वर्ग केवल आरए II encapsulating) इसलिए अन्य दृष्टिकोण नियुक्ति new होगा:

float* device_data = new (cudaDevice) float[SIZE]; 
// Use `device_data` … 
operator delete [](device_data, cudaDevice); 

यहाँ, cudaDevice केवल करने के लिए एक टैग के रूप में कार्य करता है अधिभार ट्रिगर करें। हालांकि, सामान्य प्लेसमेंट new में यह प्लेसमेंट इंगित करेगा, मुझे सिंटैक्स अजीब रूप से सुसंगत और शायद कक्षा का उपयोग करने के लिए भी बेहतर लगता है।

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

तो, मेरे सवाल का वास्तव में तीन गुना है:

  1. अपना स्थान new अधिभार शब्दार्थ सही है? क्या यह स्मृति रिसाव करता है?
  2. क्या किसी के पास भविष्य में सीयूडीए विकास के बारे में जानकारी है जो इस सामान्य दिशा में जाती है (चलिए इसका सामना करते हैं: सी ++ एस * सीके में सी इंटरफेस)?
  3. मैं इसे लगातार तरीके से कैसे ले सकता हूं (विचार करने के लिए अन्य एपीआई हैं, उदाहरण के लिए न केवल डिवाइस मेमोरी बल्कि एक स्थिर मेमोरी स्टोर और बनावट मेमोरी भी है)?

// Singleton tag for CUDA device memory placement. 
struct CudaDevice { 
    static CudaDevice const& get() { return instance; } 
private: 
    static CudaDevice const instance; 
    CudaDevice() { } 
    CudaDevice(CudaDevice const&); 
    CudaDevice& operator =(CudaDevice const&); 
} const& cudaDevice = CudaDevice::get(); 

CudaDevice const CudaDevice::instance; 

inline void* operator new [](std::size_t nbytes, CudaDevice const&) { 
    void* ret; 
    cudaMalloc(&ret, nbytes); 
    return ret; 
} 

inline void operator delete [](void* p, CudaDevice const&) throw() { 
    cudaFree(p); 
} 

template <typename T> 
class CudaArray { 
public: 
    explicit 
    CudaArray(std::size_t size) : size(size), data(new (cudaDevice) T[size]) { } 

    operator T*() { return data; } 

    ~CudaArray() { 
     operator delete [](data, cudaDevice); 
    } 

private: 
    std::size_t const size; 
    T* const data; 

    CudaArray(CudaArray const&); 
    CudaArray& operator =(CudaArray const&); 
}; 

यहां कार्यरत सिंगलटन के बारे में: हाँ, मैं अपनी कमियां के बारे में पता कर रहा हूँ। हालांकि, ये इस संदर्भ में प्रासंगिक नहीं हैं। मुझे बस एक छोटा प्रकार का टैग था जो कॉपी करने योग्य नहीं था। बाकी सब कुछ (यानी बहुप्रचार विचार, प्रारंभिक समय) लागू नहीं होता है।

+1

सिंगलटन का आपका कार्यान्वयन सबसे खतरनाक है। सी ++ में सिंगलटन बनाने के तरीके के बारे में कई अन्य चर्चाएं देखें। –

+0

हाँ, आप सही हैं। हालांकि, कोड के नीचे मेरा नया स्पष्टीकरण देखें। –

उत्तर

5

मैं नियुक्ति के नए दृष्टिकोण के साथ जाऊंगा। फिर मैं एक वर्ग परिभाषित करता हूं जो std :: आवंटक <> इंटरफ़ेस के अनुरूप है। सिद्धांत रूप में, आप इस वर्ग को std :: vector <> और std :: map <> और आगे में टेम्पलेट पैरामीटर के रूप में पास कर सकते हैं।

सावधान रहें, मैंने सुना है कि ऐसी चीजें करना कठिनाई से भरा हुआ है, लेकिन कम से कम आप एसटीएल के बारे में बहुत कुछ सीखेंगे। और आपको अपने कंटेनर और एल्गोरिदम का पुन: आविष्कार करने की आवश्यकता नहीं है।

+0

एक आवंटक के बारे में सोचा नहीं था। मैंने वास्तव में ऐसा पहले किया है इसलिए यह बहुत मुश्किल नहीं होना चाहिए। –

2

ऐसी कई परियोजनाएं हैं जो कुछ समान प्रयास करती हैं, उदाहरण के लिए CUDPP

इस बीच, मैंने अपना खुद का आवंटन लागू किया है और यह अच्छी तरह से काम करता है और सीधा था (> 95% बॉयलरप्लेट कोड)।

+0

stdcuda लिंक मर चुका है। – einpoklum

+0

@inpoklum धन्यवाद। इस बात का कारण है कि 10 वर्षीय उत्तर किसी बिंदु पर पुराना हो जाएगा। मैंने लिंक हटा दिया है। –

7

इस बीच कुछ और विकास हुए थे (सीयूडीए एपीआई के मामले में इतना नहीं, लेकिन कम से कम परियोजनाओं के मामले में सीयूडीए डेटा प्रबंधन के लिए एसटीएल जैसी दृष्टिकोण का प्रयास करने के लिए)।

सबसे विशेष रूप से NVIDIA अनुसंधान से एक परियोजना है: thrust

1

किसी को भी भविष्य CUDA घटनाओं है कि यह सामान्य दिशा में जाने के बारे में जानकारी है (जाने क्यों न हम स्वीकार: सी ++ रों * सी.के. में सी इंटरफेस)?

कुछ है कि जैसे हाँ, मैं किया है:

https://github.com/eyalroz/cuda-api-wrappers/

CUDA के लिए NVIDIA के क्रम एपीआई दोनों में C और C++ कोड के उपयोग के लिए करना है। इस प्रकार, यह सी-स्टाइल एपीआई का उपयोग करता है, निचला आम संप्रदाय (टेम्पलेटेड फ़ंक्शन ओवरलोड के कुछ उल्लेखनीय अपवादों के साथ)।

रनटाइम एपीआई के आसपास रैपरों की यह लाइब्रेरी हमें रनटाइम एपीआई का उपयोग करने के लिए सी ++ (कुछ सी ++ 11 सहित) की कई विशेषताओं को गले लगाने की अनुमति देने के लिए है - लेकिन अभिव्यक्ति को कम किए बिना या अमूर्तता के स्तर को बढ़ाने के बिना (जैसा कि, उदाहरण के लिए, जोर पुस्तकालय)। कूडा-एपीआई-रैपर का उपयोग करके, आपके पास अभी भी आपके डिवाइस, स्ट्रीम, इवेंट आदि हैं - लेकिन वे अधिक सी ++ - बेवकूफ तरीकों से काम करने के लिए अधिक सुविधाजनक होंगे।