2011-08-02 106 views
1

我有一個CUDA程序似乎正在打擊某些資源的某種限制,但我無法弄清楚這個資源是什麼。這裏是內核函數:CUDA限制似乎已經達到,但是有什麼限制?

__global__ void DoCheck(float2* points, int* segmentToPolylineIndexMap, 
         int segmentCount, int* output) 
{ 
    int segmentIndex = threadIdx.x + blockIdx.x * blockDim.x; 
    int pointCount = segmentCount + 1; 

    if(segmentIndex >= segmentCount) 
     return; 

    int polylineIndex = segmentToPolylineIndexMap[segmentIndex]; 
    int result = 0; 
    if(polylineIndex >= 0) 
    { 
     float2 p1 = points[segmentIndex]; 
     float2 p2 = points[segmentIndex+1]; 
     float2 A = p2; 
     float2 a; 
     a.x = p2.x - p1.x; 
     a.y = p2.y - p1.y; 

     for(int i = segmentIndex+2; i < segmentCount; i++) 
     { 
      int currentPolylineIndex = segmentToPolylineIndexMap[i]; 

      // if not a different segment within out polyline and 
      // not a fake segment 
      bool isLegit = (currentPolylineIndex != polylineIndex && 
       currentPolylineIndex >= 0);  

      float2 p3 = points[i]; 
      float2 p4 = points[i+1]; 
      float2 B = p4; 
      float2 b; 
      b.x = p4.x - p3.x; 
      b.y = p4.y - p3.y; 

      float2 c; 
      c.x = B.x - A.x; 
      c.y = B.y - A.y; 

      float2 b_perp; 
      b_perp.x = -b.y; 
      b_perp.y = b.x; 

      float numerator = dot(b_perp, c); 
      float denominator = dot(b_perp, a); 
      bool isParallel = (denominator == 0.0); 

      float quotient = numerator/denominator; 
      float2 intersectionPoint; 
      intersectionPoint.x = quotient * a.x + A.x; 
      intersectionPoint.y = quotient * a.y + A.y; 

      result = result | (isLegit && !isParallel && 
       intersectionPoint.x > min(p1.x, p2.x) && 
       intersectionPoint.x > min(p3.x, p4.x) && 
       intersectionPoint.x < max(p1.x, p2.x) && 
       intersectionPoint.x < max(p3.x, p4.x) && 
       intersectionPoint.y > min(p1.y, p2.y) && 
       intersectionPoint.y > min(p3.y, p4.y) && 
       intersectionPoint.y < max(p1.y, p2.y) && 
       intersectionPoint.y < max(p3.y, p4.y)); 
     } 
    } 

    output[segmentIndex] = result; 
} 

這裏被執行內核函數調用:是

DoCheck<<<702, 32>>>(
    (float2*)devicePoints, 
    deviceSegmentsToPolylineIndexMap, 
    numSegments, 
    deviceOutput); 

參數的尺寸如下:

  • devicePoints = 22464個float2s = 179,712字節
  • deviceSegmentsToPolylineIndexMap = 22,463整數= 89,852字節
  • 個numSegments = 1個INT = 4個字節
  • deviceOutput = 22463個整數= 89852個字節

當我執行這個內核,它崩潰視頻卡。這似乎是我遇到了某種限制,因爲如果我使用DoCheck<<<300, 32>>>(...);執行內核,它可以工作。要明確,參數是相同的,只是塊的數量是不同的。

任何想法爲什麼一個崩潰的視頻驅動程序,而另一個不?失敗的人似乎仍然在牌的數量限制之內。

更新 在我的系統配置的更多信息:

  • 顯卡:nVidia的8800GT
  • CUDA版本:1.1
  • 操作系統:Windows Server 2008 R2

我也在筆記本電腦上用以下配置嘗試過,但得到了AME結果:

  • 顯卡:的NVIDIA Quadro FX 880M
  • CUDA版本:1.2
  • 操作系統:Windows 7 64位
+0

如果這是一塊顯卡,可能掛鐘時間。顯示驅動程序有一個看門狗定時器,可以殺死需要幾秒鐘才能完成的內核。實施細節和解決方法是特定於操作系統的。你使用的是什麼操作系統,卡和CUDA版本? – talonmies

+0

有趣。好的,我會用這些信息更新問題。 –

+0

看門狗定時器在Windows上仍然是個問題嗎?如果是這樣,你的內核可能需要很長時間才能執行。 – Eric

回答

4

正在被耗盡的時間資源。在當前所有CUDA平臺上,顯示驅動程序都包含一個看門狗定時器,它可以殺死任何需要幾秒鐘才能執行的內核。在運行顯示器的卡上運行代碼受此限制。

在您使用的是WDDM Windows平臺上,有三種可能的解決方案/變通:

  1. 得到一個特斯拉卡,並使用TCC驅動程序,它消除了該問題完全
  2. 嘗試修改註冊表設置來增加計時器的限制(谷歌的TdrDelay註冊表項的更多信息,但我不是一個Windows用戶,不能是更具體的比)
  3. 修改您的內核代碼爲「重入」,並進程數據並行工作負載在幾個內核啓動而不是一個。內核啓動開銷並不是那麼大,並且根據您使用的算法,在幾次內核運行中處理工作量通常很容易實現。
+0

對於解決方案#2,這看起來像一個很好的頁面:http://msdn.microsoft.com/en-us/windows/hardware/gg487368 –

+0

還有一個問題......那麼超時看待CUDA ?整個內核調用?每塊?每個線程? –

+1

任何主機API函數在看門狗限制內都不會向顯卡驅動程序提供GPU,將觸發驅動程序重置事件。在你的情況下,這意味着整個內核(技術上在最近的CUDA版本的WDDM平臺上,它也可能意味着任何其他的API操作也會被內核批處理)。 – talonmies