मैंने देखा है कि डेटा को हाल के उच्च अंत वाले GPU में स्थानांतरित करना CPU में वापस इकट्ठा करने की तुलना में तेज़ है। पुराने Nvidia K20 और PCIE के साथ हाल ही में Nvidia P100 पर चल रहे मैथवर्क्स टेक-सपोर्ट द्वारा मुझे प्रदान किए गए बेंचमार्किंग फ़ंक्शन का उपयोग करने वाले परिणाम यहां दिए गए हैं:

Using a Tesla P100-PCIE-12GB GPU.
Achieved peak send speed of 11.042 GB/s
Achieved peak gather speed of 4.20609 GB/s

Using a Tesla K20m GPU.
Achieved peak send speed of 2.5269 GB/s
Achieved peak gather speed of 2.52399 GB/s

मैंने संदर्भ के लिए नीचे बेंचमार्क फ़ंक्शन संलग्न किया है। P100 पर विषमता का कारण क्या है? क्या यह प्रणाली निर्भर है या यह हाल के उच्च अंत GPU पर आदर्श है? क्या इकट्ठा करने की गति बढ़ाई जा सकती है?

gpu = gpuDevice();
fprintf('Using a %s GPU.\n', gpu.Name)
sizeOfDouble = 8; % Each double-precision number needs 8 bytes of storage
sizes = power(2, 14:28);

sendTimes = inf(size(sizes));
gatherTimes = inf(size(sizes));
for ii=1:numel(sizes)
    numElements = sizes(ii)/sizeOfDouble;
    hostData = randi([0 9], numElements, 1);
    gpuData = randi([0 9], numElements, 1, 'gpuArray');
    % Time sending to GPU
    sendFcn = @() gpuArray(hostData);
    sendTimes(ii) = gputimeit(sendFcn);
    % Time gathering back from GPU
    gatherFcn = @() gather(gpuData);
    gatherTimes(ii) = gputimeit(gatherFcn);
end
sendBandwidth = (sizes./sendTimes)/1e9;
[maxSendBandwidth,maxSendIdx] = max(sendBandwidth);
fprintf('Achieved peak send speed of %g GB/s\n',maxSendBandwidth)
gatherBandwidth = (sizes./gatherTimes)/1e9;
[maxGatherBandwidth,maxGatherIdx] = max(gatherBandwidth);
fprintf('Achieved peak gather speed of %g GB/s\n',max(gatherBandwidth))

संपादित करें: अब हम जानते हैं कि यह सिस्टम पर निर्भर नहीं है (टिप्पणियां देखें)। मैं अभी भी विषमता का कारण जानना चाहता हूं या यदि इसे बदला जा सकता है।

12
avgn 12 मई 2018, 04:35
1
आपके दूसरे प्रश्न का उत्तर देने के लिए, मैं क्वाड्रो एम5000 जीपीयू पर परिणाम पुन: पेश कर सकता हूं, यहां मेरे पास 10.0442 जीबी/एस की चोटी की गति है और पीक इकट्ठा गति 3.66208 जीबी/एस है। तो ऐसा नहीं लगता कि यह सिस्टम पर निर्भर है।
 – 
Nicky Mattsson
12 मई 2018, 10:17
धन्यवाद! मैंने इसे इसी तरह के परिणामों के साथ अन्य प्रणालियों पर भी आजमाया। तो अब हम पुष्टि कर सकते हैं कि यह सिस्टम पर निर्भर नहीं है।
 – 
avgn
12 मई 2018, 21:33
1
जीपीयू को ध्यान में रखते हुए मुख्य रूप से स्क्रीन पर ग्राफिक्स का उत्पादन करने के लिए डिज़ाइन किया गया है, अपलोड गति को डाउनलोड गति पर प्राथमिकता देना समझ में आता है।
 – 
Cris Luengo
13 मई 2018, 00:00
1
मुझे लगता है कि पूर्णता के लिए, MATLAB से संबंधित विचित्रताओं को रद्द करने के लिए इस बेंचमार्क को एक अलग वातावरण/भाषा में भी किया जाना चाहिए।
 – 
Dev-iL
23 मई 2018, 12:15
1
गति का शिखर प्रतिनिधि है? मैं निश्चित रूप से अधिक औसत पर भरोसा करूंगा।
 – 
Ander Biguri
23 मई 2018, 14:07

2 जवाब

सबसे बढ़िया उत्तर

यह उनकी मशीन से बेंचमार्क पोस्ट करने में रुचि रखने वाले किसी भी व्यक्ति के लिए एक CW है। योगदानकर्ताओं को उनके परिणामों के संबंध में भविष्य में कोई प्रश्न उठने की स्थिति में अपना विवरण छोड़ने के लिए प्रोत्साहित किया जाता है।



सिस्टम: Win10, 32GB DDR4-2400Mhz रैम, i7 6700K। मैटलैब: आर2018ए।

Using a GeForce GTX 660 GPU.
Achieved peak send speed of 7.04747 GB/s
Achieved peak gather speed of 3.11048 GB/s
Warning: The measured time for F may be inaccurate because it is running too fast. Try measuring something that takes
longer. 

योगदानकर्ता: देव-आईएल



सिस्टम: विन 7, 32 जीबी रैम, i7 4790K। मैटलैब: आर2018ए।

Using a Quadro P6000 GPU.
Achieved peak send speed of 1.43346 GB/s
Achieved peak gather speed of 1.32355 GB/s

योगदानकर्ता: देव-आईएल

3
Dev-iL 22 मई 2018, 20:52

मैं मैटलैब जीपीयू टूलबॉक्स से परिचित नहीं हूं, लेकिन मुझे संदेह है कि दूसरा स्थानांतरण (जो जीपीयू से डेटा वापस प्राप्त करता है) पहले समाप्त होने से पहले शुरू होता है।

% Time sending to GPU
sendFcn = @() gpuArray(hostData);
sendTimes(ii) = gputimeit(sendFcn);
%
%No synchronization here
%
% Time gathering back from GPU
gatherFcn = @() gather(gpuData);
gatherTimes(ii) = gputimeit(gatherFcn);

सी प्रोग्राम के लिए एक समान प्रश्न, यहां पोस्ट किया गया था:

GPU से CPU में कॉपी करना CPU को GPU में कॉपी करने की तुलना में धीमा है

उस स्थिति में, GPU पर थ्रेड लॉन्च करने और GPU से परिणाम डेटा वापस प्राप्त करने के बाद कोई स्पष्ट सिंक नहीं होता है। तो C cudaMemcpy () में डेटा वापस प्राप्त करने वाले फ़ंक्शन को डेटा स्थानांतरित करने से पहले GPU को पिछले लॉन्च किए गए थ्रेड को समाप्त करने की प्रतीक्षा करनी पड़ती है, इस प्रकार डेटा स्थानांतरण के लिए मापा गया समय बढ़ जाता है।

क्यूडा सी एपीआई के साथ, सीपीयू को पहले से लॉन्च किए गए थ्रेड को समाप्त करने के लिए जीपीयू की प्रतीक्षा करने के लिए मजबूर करना संभव है:

CudaDeviceसिंक्रनाइज़ ();

और उसके बाद ही डेटा को वापस स्थानांतरित करने के लिए समय को मापना शुरू करें।

हो सकता है कि मैटलैब में कुछ सिंक्रोनाइज़ेशन आदिम भी हो।

साथ ही उसी उत्तर में, (क्यूडा) ईवेंट के साथ समय मापने की अनुशंसा की जाती है।

डेटा ट्रांसफर के अनुकूलन पर इस पोस्ट में, सी सॉरी में भी, डेटा ट्रांसफर समय को मापने के लिए ईवेंट का उपयोग किया जाता है:

https://devblogs.nvidia.com/how-optimize-data-transfers-cuda-cc/

दोनों दिशाओं में डेटा स्थानांतरित करने का समय समान है।

1
Helder Daniel 8 मई 2019, 16:43