2012-11-23 4 views
5

मैं एक परीक्षण कार्यक्रम है कि एक युक्ति है और आकार के एक मेजबान सरणी n कर्नेल कि n धागे जो आवंटित बनाता है पैदा करेगा और उसके बाद लांच बनाने हूँ डिवाइस सरणी में प्रत्येक स्थान पर निरंतर मान 0.95f। पूरा होने के बाद, डिवाइस सरणी होस्ट होस्ट में कॉपी की जाती है और सभी प्रविष्टियां कुल होती हैं और अंतिम कुल प्रदर्शित होता है।CUDA परिणाम बहुत बड़े सरणी का उपयोग कर कचरा दिखाए, लेकिन रिपोर्ट कोई त्रुटि

नीचे दिया गया कार्यक्रम लगभग 60 मिलियन फ्लोट तक सरणी आकारों के लिए ठीक काम करता है और सही परिणाम बहुत जल्दी देता है, लेकिन 70 मिलियन तक पहुंचने पर कार्यक्रम थोड़ी देर तक लटकता प्रतीत होता है और अंततः कुल के लिए एनएएन परिणाम देता है । 60 मिलियन रन के बाद मेजबान सरणी का निरीक्षण करना यह दिखाता है कि यह 0.95 एफ के साथ सही ढंग से आबादी वाला है, लेकिन 70 मिलियन रन के बाद यह जांच कर रहा है कि यह एनएएन के साथ आबादी वाला है। जहां तक ​​मुझे पता है कि सीयूडीए में से कोई भी वापसी त्रुटियों को कॉल नहीं करता है।

मैं एक 2GB GT640m (कंप्यूट 3.0) का उपयोग कर रहा है, मुझे 1024 के एक अधिकतम ब्लॉक आकार और 2147483647

की एक अधिकतम ग्रिड आयाम मुझे यकीन है कि वहाँ कुछ इसी तरह प्राप्त करने के बेहतर तरीके हैं रहा हूँ दे रही है, और मैं करूंगा सुझाव सुनना पसंद है। लेकिन मैं यह भी समझना चाहूंगा कि यहां क्या गलत हो गया है, इसलिए मैं इससे सीख सकता हूं।

#include "cuda_runtime.h" 
#include "device_launch_parameters.h" 

#include <stdio.h> 
#include <fstream> 

void cudaErrorHandler(cudaError_t status) 
{ 
    // Cuda call returned an error, just print error for now 
    if(status != cudaSuccess) 
    { 
     printf("Error"); 
    } 
} 

__global__ void addKernel(float* _Results, int _TotalCombinations) 
{ 
    // Get thread Id 
    unsigned int Id = (blockDim.x * blockDim.y * blockIdx.x) + (blockDim.x * threadIdx.y) + threadIdx.x; 

    //If the Id is within simulation range, log it 
    if(Id < _TotalCombinations) 
    { 
     _Results[Id] = 0.95f; 
    } 
} 

#define BLOCK_DIM_X 32 
#define BLOCK_DIM_Y 32 
#define BLOCK_SIZE BLOCK_DIM_X * BLOCK_DIM_Y // Statc block size of 32*32 (1024) 
#define CUDA_CALL(x) cudaErrorHandler(x) 

int main() 
{ 
    // The number of simulations to run 
    unsigned int totalCombinations = 45000000; 

    int gridsize = 1; 

    // Work out how many blocks of size 1024 are required to perform all of totalCombinations 
    for(unsigned int totalsize = gridsize * BLOCK_SIZE; totalsize < totalCombinations; 
     gridsize++, totalsize = gridsize * BLOCK_SIZE) 
     ; 

    // Allocate host memory 
    float* host_results = new float[totalCombinations]; 
    memset(host_results, 0, sizeof(float) * totalCombinations); 
    float *dev_results = 0; 

    cudaSetDevice(0); 

    // Allocate device memory 
    CUDA_CALL(cudaMalloc((void**)&dev_results, totalCombinations * sizeof(float))); 

    dim3 grid, block; 

    block = dim3(BLOCK_DIM_X, BLOCK_DIM_Y); 

    grid = dim3(gridsize); 

    // Launch kernel 
    addKernel<<<gridsize, block>>>(dev_results, totalCombinations); 

    // Wait for synchronize 
    CUDA_CALL(cudaDeviceSynchronize()); 

    // Copy device data back to host 
    CUDA_CALL(cudaMemcpy(host_results, dev_results, totalCombinations * sizeof(float), cudaMemcpyDeviceToHost)); 

    double total = 0.0; 

    // Total the results in the host array 
    for(unsigned int i = 0; i < totalCombinations; i++) 
     total+=host_results[i]; 

    // Print results to screen 
    printf("Total %f\n", total); 

    delete[] host_results; 

    return 0; 
} 
+2

आपकी त्रुटि प्रबंधन विधि काम नहीं कर रही है। इसे साबित करने के लिए, अपने ब्लॉक मंद x और y से 50 को बदलें (2500 धागे प्रदान करना, जो अवैध है) और आपको कोई त्रुटि मुद्रित नहीं होती है। यदि आप अपनी त्रुटि प्रबंधन को ठीक करते हैं, तो आप समस्या की खोज करेंगे। आपके विफलता बिंदु पर चीजें काम नहीं कर रही हैं यह है कि आपका ग्रिडाइज (आप 1 डी ग्रिड लॉन्च कर रहे हैं) एक्स आयाम (डिफ़ॉल्ट रूप से 65535) में अधिकतम ग्रिड आकार से अधिक है। यदि आप बड़े gridsize का लाभ लेना चाहते हैं, तो आपको '-arch = sm_30' स्विच के साथ संकलित करने की आवश्यकता है। एक और नोट, आपके पास 22 का ब्लॉक एक्स आयाम है, इसकी अनुशंसा नहीं की जाती है। –

+1

@RobertCrovella मैंने अपनी त्रुटि जांच (और ब्लॉक एक्स, जो कि मेरे भाग पर एक टाइपो था) को सही किया और फिर कमांड लाइन पर स्विच जोड़ा और इससे मेरी समस्याएं हल हो गईं और सब ठीक से चल रहा है। यदि आप इसे उत्तर के रूप में सबमिट करना चाहते हैं तो मैं इसे स्वीकार करूंगा। – TVOHM

उत्तर

7

जैसा कि आपने पाया है, आपकी त्रुटि प्रबंधन विधि काम नहीं कर रही है। नीचे मैंने आपके कोड का एक संस्करण एक त्रुटि जांच विधि के साथ चिपकाया है जिसका उपयोग मैं अक्सर करता हूं। कारण आपकी विफलता बिंदु पर काम नहीं कर रहे हैं यह है कि आपका ग्रिडसाइज (आप 1 डी ग्रिड लॉन्च कर रहे हैं) एक्स आयाम में अधिकतम ग्रिड आकार (डिफ़ॉल्ट रूप से 65535, यानी 2.x तक गणना क्षमता के लिए) से अधिक है। यदि आप एक बड़े ग्रिडसाइज आयाम का लाभ लेना चाहते हैं (2^31 -1 गणना क्षमता 3.0 के साथ सीमा है), तो आपको -arch=sm_30 स्विच के साथ संकलित करने की आवश्यकता है।

बस संदर्भ के लिए यहां आपके कोड का एक संस्करण है जो एक त्रुटि-जांच विधि दिखाता है जिसे मैं अक्सर उपयोग करता हूं।

#include <stdio.h> 
#include <fstream> 


#define cudaCheckErrors(msg) \ 
    do { \ 
     cudaError_t __err = cudaGetLastError(); \ 
     if (__err != cudaSuccess) { \ 
      fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \ 
       msg, cudaGetErrorString(__err), \ 
       __FILE__, __LINE__); \ 
      fprintf(stderr, "*** FAILED - ABORTING\n"); \ 
      exit(1); \ 
     } \ 
    } while (0) 

__global__ void addKernel(float* _Results, int _TotalCombinations) 
{ 
    // Get thread Id 
    unsigned int Id = (blockDim.x * blockDim.y * blockIdx.x) + (blockDim.x * threadIdx.y) + threadIdx.x; 

    //If the Id is within simulation range, log it 
    if(Id < _TotalCombinations) 
    { 
     _Results[Id] = 0.95f; 
    } 
} 

#define BLOCK_DIM_X 32 
#define BLOCK_DIM_Y 32 
#define BLOCK_SIZE BLOCK_DIM_X * BLOCK_DIM_Y // Statc block size of 32*32 (1024) 

int main() 
{ 
    // The number of simulations to run 
    unsigned int totalCombinations = 65000000; 

    int gridsize = 1; 

    // Work out how many blocks of size 1024 are required to perform all of totalCombinations 
    for(unsigned int totalsize = gridsize * BLOCK_SIZE; totalsize < totalCombinations; 
     gridsize++, totalsize = gridsize * BLOCK_SIZE) 
     ; 
    printf("gridsize = %d, blocksize = %d\n", gridsize, BLOCK_SIZE); 
    // Allocate host memory 
    float* host_results = new float[totalCombinations]; 
    memset(host_results, 0, sizeof(float) * totalCombinations); 
    float *dev_results = 0; 

    cudaSetDevice(0); 

    // Allocate device memory 
    cudaMalloc((void**)&dev_results, totalCombinations * sizeof(float)); 
    cudaCheckErrors("cudaMalloc fail"); 

    dim3 grid, block; 

    block = dim3(BLOCK_DIM_X, BLOCK_DIM_Y); 

    grid = dim3(gridsize); 

    // Launch kernel 
    addKernel<<<gridsize, block>>>(dev_results, totalCombinations); 
    cudaCheckErrors("kernel fail"); 
    // Wait for synchronize 
    cudaDeviceSynchronize(); 
    cudaCheckErrors("sync fail"); 

    // Copy device data back to host 
    cudaMemcpy(host_results, dev_results, totalCombinations * sizeof(float), cudaMemcpyDeviceToHost); 
    cudaCheckErrors("cudaMemcpy 2 fail"); 

    double total = 0.0; 

    // Total the results in the host array 
    for(unsigned int i = 0; i < totalCombinations; i++) 
     total+=host_results[i]; 

    // Print results to screen 
    printf("Total %f\n", total); 

    delete[] host_results; 

    return 0; 
} 
+1

आपकी मदद के लिए धन्यवाद, भविष्य में मैं इस त्रुटि जांच विधि का उपयोग करूंगा। – TVOHM

+1

महान उत्तर। आज भी मेरी मदद की। धन्यवाद! –

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