【问题标题】:Distribute the threads between blocks in CUDA在 CUDA 中的块之间分配线程
【发布时间】:2016-02-21 15:15:30
【问题描述】:

我正在使用 CUDA 进行一个项目。我第一次只使用了一个块,Dim 8*8 作为我的矩阵。然后我计算指数如下:

int idx = blockIdx.x * blockDim.x + threadIdx.x;  
int idy = blockIdx.y * blockDim.y + threadIdx.y;  

它给了我一个正确的答案。之后,我想在块之间分配线程以测量性能。我使网格变暗为(2,1),块变暗为(4,8)。

当我手动调试代码时,它似乎给了我正确的索引而不改变上面提到的公式。但是当我运行程序时,屏幕挂起,结果全为零。

我做错了什么,我该如何解决这个问题?

这是核函数

__global__ void cover_fault(int *a,int *b, int *c, int *d, int *mulFV1, int *mulFV2,     int *checkDalU1, int *checkDalU2, int N)  

 {  
//Fig.2
__shared__ int f[9][9];
__shared__ int compV1[9],compV2[9];
int dalU1[9] , dalU2[9];
int Ra=2 , Ca=2;
for (int i = 0 ; i < N ; i++)
  for (int j = 0 ; j < N ; j++)
         f[i][j]=0;

f[3][0] = 1;
f[0][2] = 1;
f[0][6] = 1;
f[3][7] = 1;
f[2][4] = 1;
f[6][4] = 1;
f[7][1] = 1; 

int t =0 ,A = 1,B = 1 , UTP = 5 , LTP = -5 , U_max = 40 , U_min = -160;
bool flag = true;
int sumV1, sumV2;
int checkZero1 , checkZero2;


int idx = blockIdx.x * blockDim.x + threadIdx.x;  
int idy = blockIdx.y * blockDim.y + threadIdx.y;  

while ( flag == true)
{
    if ( c[idy] == 0 )
            compV1[idy] = 1;

       else if ( c[idy]==1)
                compV1[idy] = 0 ;

       if ( d[idy] == 0 )
            compV2[idy] = 1;

       else if ( d[idy]==1 )
                  compV2[idy] = 0 ;


   sumV1 = reduce ( c, N );
   sumV2 = reduce ( d, N );


   if (idx<N && idy <N)    
    {        
     if(idx==0)                  
          mulFV1[idy]=0;     
     if(idy==0)      
          mulFV2[idx]=0;               

     __syncthreads();     

     atomicAdd(&(mulFV1[idy]),f[idy][idx]*compV2[idx]);     
     atomicAdd(&(mulFV2[idx]),f[idy][idx]*compV1[idy]);   

      } 


    dalU1[idy] = ( -1*A*( sumV1 - Ra )) + (B * mulFV1[idy] * compV1[idy]) ;
    dalU2[idy] = ( -1*A*( sumV2 - Ca )) + (B * mulFV2[idy] * compV2[idy]) ;


    a[idy] = a[idy] + dalU1[idy];
    b[idy] = b[idy] + dalU2[idy];


       if ( a[idy] > U_max )
               a[idy] = U_max;
       else
           if (a[idy] < U_min )
                a[idy] = U_min;

       if ( b[idy] > U_max )
                 b[idy] = U_max;
       else
           if (b[idy] < U_min )
                b[idy] = U_min;


      if (dalU1[idy]==0)
           checkDalU1[idy]=0;
         else
            checkDalU1[idy]=1;

      if (dalU2[idy]==0)
           checkDalU2[idy]=0;
            else
               checkDalU2[idy]=1;

       __syncthreads();     
      checkZero1 = reduce(checkDalU1,N);
      checkZero2 = reduce(checkDalU2,N);

      if ( checkZero1==0 && checkZero2==0)
               flag = false;


      else
      {

       if ( a[idy] > UTP )
              c[idy] = 1;
           else
               if ( a[idy] < LTP )
                      c[idy] = 0 ;

            if ( b[idy] > UTP )
                   d[idy] = 1;
           else
               if ( b[idy] < LTP )
                      d[idy] = 0 ;  

      t++;

      }//end else 
      sumV1=0;
      sumV2=0;
      mulFV1[idy]=0;
      mulFV2[idy]=0;
      } //end while

}//end function

【问题讨论】:

  • 如果您想要答案,请发布一些实际代码。否则,您的问题会简化为“我的程序不起作用。为什么?”。你不能指望有人能够回答这个问题,对吗?
  • @talonmies 我的代码超过 300 行,我一直在玩代码,直到我确定问题是当我有超过 1 个块时,大部分代码都是数学的声明..
  • @asma - 然后删除数学并只传入和传出数据,直到您获得正确传递数据的多块场景。如果您自己没有发现问题,请发布简化代码。然后把数学 bsck 应该很简单。
  • @SteveFallows 谢谢你的建议,我注释了整个代码并将上面的索引结果打印出来。索引是对的。
  • @talonmies : 这是一个归约函数,添加行或列的元素。我从 SDK 中得到它,几乎没有修改

标签: cuda


【解决方案1】:

在您的索引计算中,idx 将为您提供列索引,idy 为您提供行索引。您是否以M[idy][idx] 的身份访问您的矩阵?

cuda 线程是根据正交系统组织的:X 是水平的,Y 是垂直的。所以如果你说实际矩阵中的点 M[0][1] 它是 M[1][0]。

【讨论】:

  • 欢迎 Tudor,idx 将给我行,idy 将给我列。是的,我想访问二维数组,我之前对其进行了测试并给出了正确的结果。
  • @asma: idx 会给你列,而不是行,idy 行。尝试扭转它们,看看会发生什么。请记住,在正交系统上,X 是水平轴,Y 是垂直轴。
  • 我交换了 X 和 Y 的索引。但它仍然给了我同样的问题 .. 挂起和归零:(
  • 感谢您的支持,我将在答案中发布我的代码以便清楚。我通过更改数组的大小和迭代次数来调试我的代码,我发现它卡在某个点上,我认为是因为内存.. 这是异常(Move.exe 中 0x75289617 的第一次机会异常:Microsoft C++ 异常:cudaError_enum 在内存位置 0x0012f81c..).. 有什么想法吗?!
猜你喜欢
  • 2012-09-05
  • 2014-11-13
  • 2011-04-25
  • 1970-01-01
  • 2016-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-13
相关资源
最近更新 更多