Odd-Even使用cuda编程排序

时间:2015-04-11 17:53:20

标签: c cuda

我正在尝试用cuda-c语言实现奇偶排序程序。但是,每当我将0作为输入数组中的一个元素时,结果数组就没有正确排序。但是,在其他情况下,它适用于其他输入。我不明白代码的问题是什么这是我的代码:

#include<stdio.h>
#include<cuda.h>
#define N 5

__global__ void sort(int *c,int *count)
{
    int l;
    if(*count%2==0)
          l=*count/2;
    else
         l=(*count/2)+1;
    for(int i=0;i<l;i++)
    {
            if(threadIdx.x%2==0)  //even phase
            {
                if(c[threadIdx.x]>c[threadIdx.x+1])
                {
                    int temp=c[threadIdx.x];
                    c[threadIdx.x]=c[threadIdx.x+1];
                    c[threadIdx.x+1]=temp;
                }

            __syncthreads();
            }
            else     //odd phase
            {
                if(c[threadIdx.x]>c[threadIdx.x+1])
                {
                    int temp=c[threadIdx.x];
                    c[threadIdx.x]=c[threadIdx.x+1];
                    c[threadIdx.x+1]=temp;
                }

            __syncthreads();
            }
    }//for

}



int main()
{int a[N],b[N],n;
    printf("enter size of array");
    scanf("%d",&n);
    print("enter the elements of array");
  for(int i=0;i<n;i++)
  {
    scanf("%d",&a[i]);
  }
  printf("ORIGINAL ARRAY : \n");
  for(int i=0;i<n;i++)
          {

          printf("%d ",a[i]);
          }
  int *c,*count;
  cudaMalloc((void**)&c,sizeof(int)*N);
  cudaMalloc((void**)&count,sizeof(int));
  cudaMemcpy(c,&a,sizeof(int)*N,cudaMemcpyHostToDevice);
  cudaMemcpy(count,&n,sizeof(int),cudaMemcpyHostToDevice);
  sort<<< 1,n >>>(c,count);
  cudaMemcpy(&b,c,sizeof(int)*N,cudaMemcpyDeviceToHost);
  printf("\nSORTED ARRAY : \n");
  for(int i=1;i<=n;i++)
      {
         printf("%d ",b[i]);
      }

}

1 个答案:

答案 0 :(得分:4)

您的内核代码有两个我可以看到的主要错误:

  1. 在奇数阶段(对于偶数长度数组,甚至奇数长度数组的相位),您的最后一个线程将在c[threadIdx.x+1]处超出范围。例如,对于4个线程,它们编号为0,1,2,3。线程3是奇数,但如果您访问c[3+1],那么这不是数组中已定义的元素。我们可以通过限制每个阶段来处理所有线程而不是最后一个线程来解决这个问题。

  2. 您在条件语句中使用__syncthreads(),该语句不允许所有线程到达屏障。这是编码错误。阅读documentation。我们可以通过调整条件区域内的代码来解决这个问题。

  3. 在主代码中,您的最终打印输出语句索引错误:

    for(int i=1;i<=n;i++)
    

    应该是:

    for(int i=0;i<n;i++)
    

    你也有拼写错误:

    print("enter the elements of array");
    

    我认为应该是printf

    以下代码修复了上述错误,对于长度为5的数组(N上的硬编码限制),似乎可以正常运行。即使你增加N,我也不确定这会超出warp的大小,当然也不会超出threadblock大小,但希望你已经知道了(如果没有,请阅读{{ 3}})。

    “已修复”代码:

    #include<stdio.h>
    #include<cuda.h>
    #define N 5
    
    #define intswap(A,B) {int temp=A;A=B;B=temp;}
    
    __global__ void sort(int *c,int *count)
    {
        int l;
        if(*count%2==0)
              l=*count/2;
        else
             l=(*count/2)+1;
        for(int i=0;i<l;i++)
        {
                if((!(threadIdx.x&1)) && (threadIdx.x<(*count-1)))  //even phase
                {
                    if(c[threadIdx.x]>c[threadIdx.x+1])
                      intswap(c[threadIdx.x], c[threadIdx.x+1]);
                }
    
                __syncthreads();
                if((threadIdx.x&1) && (threadIdx.x<(*count-1)))     //odd phase
                {
                    if(c[threadIdx.x]>c[threadIdx.x+1])
                      intswap(c[threadIdx.x], c[threadIdx.x+1]);
                }
                __syncthreads();
        }//for
    
    }
    
    
    
    int main()
    {int a[N],b[N],n;
        printf("enter size of array");
        scanf("%d",&n);
        if (n > N) {printf("too large!\n"); return 1;}
        printf("enter the elements of array");
      for(int i=0;i<n;i++)
      {
        scanf("%d",&a[i]);
      }
      printf("ORIGINAL ARRAY : \n");
      for(int i=0;i<n;i++)
              {
    
              printf("%d ",a[i]);
              }
      int *c,*count;
      cudaMalloc((void**)&c,sizeof(int)*N);
      cudaMalloc((void**)&count,sizeof(int));
      cudaMemcpy(c,&a,sizeof(int)*N,cudaMemcpyHostToDevice);
      cudaMemcpy(count,&n,sizeof(int),cudaMemcpyHostToDevice);
      sort<<< 1,n >>>(c,count);
      cudaMemcpy(&b,c,sizeof(int)*N,cudaMemcpyDeviceToHost);
      printf("\nSORTED ARRAY : \n");
      for(int i=0;i<n;i++)
          {
             printf("%d ",b[i]);
          }
    
      printf("\n");
    }
    

    关于doc link about __syncthreads()的常规叙述属于此处。