Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Parallel processing 提前退出线程是否会中断块中CUDA线程之间的同步?_Parallel Processing_Cuda_Synchronization - Fatal编程技术网

Parallel processing 提前退出线程是否会中断块中CUDA线程之间的同步?

Parallel processing 提前退出线程是否会中断块中CUDA线程之间的同步?,parallel-processing,cuda,synchronization,Parallel Processing,Cuda,Synchronization,我正在用CUDA实现一个特定的图像处理算法,我对线程同步问题有一些疑问 眼前的问题可以这样解释: 我们有一个大小为W*H的图像。对于图像的每个像素,我需要运行9个相同的数据并行处理,每个处理给出一个值数组作为结果(整个算法的数组长度相同,比如说N,约为20或30)。对于每个像素,这9个过程将在完成计算后在最终阵列(每个像素的单个阵列)中累积结果 为了将其并行化,我设计了以下结构: 我生成尺寸为(10,10,9)的块,这意味着每个线程块将处理一个10*10大小的子图像,每个线程将处理单个像素的9个

我正在用CUDA实现一个特定的图像处理算法,我对线程同步问题有一些疑问

眼前的问题可以这样解释:

我们有一个大小为W*H的图像。对于图像的每个像素,我需要运行9个相同的数据并行处理,每个处理给出一个值数组作为结果(整个算法的数组长度相同,比如说N,约为20或30)。对于每个像素,这9个过程将在完成计算后在最终阵列(每个像素的单个阵列)中累积结果

为了将其并行化,我设计了以下结构: 我生成尺寸为(10,10,9)的块,这意味着每个线程块将处理一个10*10大小的子图像,每个线程将处理单个像素的9个相同处理中的1个。在这种情况下,网格尺寸将为(W/10,H/10,1)。对于线程块,我将分配一个长度为100*N的共享内存数组,每个线程将根据其当前像素的坐标写入相应的共享内存位置。因此,我需要与atomicAdd和_synchthreads()进行同步

这里的问题是,如果一个像素的值为零,那么我们根本不需要对它进行处理,所以我想退出这样的像素,否则我将做不必要的工作,因为图像的大部分由零(背景)组成。因此,我想写下如下内容:

//X and Y are the coordinates of the current pixel in the input image.
//threadIdx.z gives the index of the process among the 9 for the current pixel. 

int X=blockIdx.x * blockDim.x + threadIdx.x;
int Y=blockIdx.y * blockDim.y + threadIdx.y;
int numOfProcessForTheCurrPixel=threadIdx.z;
int linearIndexOfPixelInBlock=threadIdx.y * blockDim.x + threadIdx.x;

unsigned short pixelValue=tex2D(image,X,Y);
//Here, threads processing zero-pixels will exit immediately.
if(pixelValue==0)
 return;

float resultArray[22];
//Fill the result array according to our algorithm, mostly irrelevant stuff.
ProcessPixel(resultArray,X,Y,numOfProcessForTheCurrPixel);

for(int i=0;i<22;i++)
    atomicAdd(&__sharedMemoryArray[22*linearIndexOfPixelInBlock + i],resultArray[i]);

 __syncthreads(); 
 //Then copy from the shared to the global memory and etc. 
//X和Y是输入图像中当前像素的坐标。
//z给出当前像素的9个进程的索引。
intx=blockIdx.X*blockDim.X+threadIdx.X;
int Y=blockIdx.Y*blockDim.Y+threadIdx.Y;
int numofprocessforthecurrpoixel=threadIdx.z;
int linearIndexOfPixelInBlock=threadIdx.y*blockDim.x+threadIdx.x;
无符号短像素值=tex2D(图像,X,Y);
//这里,处理零像素的线程将立即退出。
如果(像素值==0)
返回;
浮动结果数组[22];
//根据我们的算法填充结果数组,大部分是不相关的内容。
ProcessPixel(currPixel的结果光线、X、Y、numProcessforthecurrPixel);

对于(int i=0;i为了避免产生死锁,所有线程都需要无条件地点击_synchthreads()。在您的示例中,您可以通过将返回替换为一个if语句来实现这一点,该语句跳过函数的大部分,直接指向零像素情况下的_synchthreads()

unsigned short pixelValue=tex2D(image,X,Y);
//If there's nothing to compute, jump over all the computation stuff
if(pixelValue!=0)
{

    float resultArray[22];
    //Fill the result array according to our algorithm, mostly irrelevant stuff.
    ProcessPixel(resultArray,X,Y,numOfProcessForTheCurrPixel);

    for(int i=0;i<22;i++)
        atomicAdd(&__sharedMemoryArray[22*linearIndexOfPixelInBlock + i],resultArray[i]);

}

__syncthreads(); 

if (pixelValue != 0)
{
    //Then copy from the shared to the global memory and etc. 
}
无符号短像素值=tex2D(图像,X,Y);
//如果没有什么可计算的,跳过所有的计算内容
如果(像素值!=0)
{
浮动结果数组[22];
//根据我们的算法填充结果数组,大部分是不相关的内容。
ProcessPixel(currPixel的结果光线、X、Y、numProcessforthecurrPixel);

对于(int i=0;i您的代码是死锁的一个配方。请参阅链接线程以获得全面的答案。我明白了,因此warp中的所有线程实际上都必须达到barrier指令。那么,在我的情况下,可以做什么呢?如何在不做不必要工作的情况下退出零像素块,同时避免死锁和同步问题?以及另一个问题是,在链接线程中,它说命中屏障指令的线程数是由扭曲大小增加的,而不是由活动线程的数量增加的。因此,调度程序可能会从当前线程块开始新扭曲的过程,直到它也命中屏障。那么,在这种情况下,系统如何检查所有块中的线程命中屏障,它是否将到达计数与某个值进行比较,例如“(ceil((块中的线程数)/(扭曲大小))+1)*扭曲大小”或者什么?我不明白这是如何导致死锁的?请记住,GPU上的多个线程并不是彼此独立执行的。warp中的所有线程同时执行同一条指令。在if语句中,如果一个线程使用if子句,而所有其他线程使用else子句,则一个线程将执行if cla在其他线程空闲时使用,那么else子句线程将在一个线程空闲时执行。在if语句结束时,线程将重新同步执行相同的指令。我现在知道应该如何编写内核代码,但我仍然对因此,如果扭曲中的任何线程执行bar指令,就好像扭曲中的所有线程都执行了bar指令一样。"引用指南的一部分。假设一个线程处理了if子句的else部分,其他线程采用了if方式,我们在else部分中有一个屏障。因此,根据引用的句子,假设经线中的所有线程都碰到屏障,并根据经线大小增加到达计数,因此所有线程都被视为阻塞。因此,这怎么会导致僵局?