是否有一种简单的方法(谷歌尚未提供...)从单个输入数组分配每块共享内存区域,以便可能存在重叠?
简单的例子是字符串搜索;看到我想要输入文本,让每个块中的每个线程搜索从text [thread_id]开始的模式,但是希望分配给每个块的数据按模式长度重叠,以便匹配跨越边界的情况是还是找到了。
即,每个块上分配给共享内存的总内存大小为
(blocksize+patternlength)*sizeof(char)
我可能遗漏了一些简单的东西,目前我正在通过CUDA指南,但我会很感激一些指导。
更新:我怀疑有些人误解了我的问题(或者我误解了)。
假设我有一个数据集QWERTYUIOP,我想搜索一个3个字符的匹配,并且我将数据集(任意)切成4个每个线程块; QWER TYUI OPxx
这很容易实现,但如果3个字符匹配实际上正在寻找IOP,则算法会失败。
在这种情况下,我想要的是每个块在共享内存中的位置:
QWERTY TYUIOP OPxxxx
即为每个块分配块大小+ patternlength-1字符,因此不会出现内存边界问题。
希望能更好地解释事情。
由于@jmilloy持续......:P
//VERSION 1: Simple
__global__ void gpuSearchSimple(char *T, int lenT, char *P, int lenP, int *pFound)
{
int startIndex = blockDim.x*blockIdx.x + threadIdx.x;
int fMatch = 1;
for (int i=0; i < lenP; i++)
{
if (T[startIndex+i] != P[i]) fMatch = 0;
}
if (fMatch) atomicMin(pFound, startIndex);
}
//VERSION 2: Texture
__global__ void gpuSearchTexture(int lenT, int lenP, int *pFound)
{
int startIndex = blockDim.x*blockIdx.x + threadIdx.x;
int fMatch = 1;
for (int i=0; i < lenP; i++)
{
if (tex1Dfetch(texT,startIndex+i) != tex1Dfetch(texP,i)) fMatch = 0;
}
if (fMatch) atomicMin(pFound, startIndex);
}
//Version 3: Shared
__global__ void gpuSearchTexSha(int lenT, int lenP, int *pFound)
{
extern __shared__ char shaP[];
for (int i=0;threadIdx.x+i<lenP; i+=blockDim.x){
shaP[threadIdx.x+i]= tex1Dfetch(texP,threadIdx.x+i);
}
__syncthreads();
//At this point shaP is populated with the pattern
int startIndex = blockDim.x*blockIdx.x + threadIdx.x;
// only continue if an earlier instance hasn't already been found
int fMatch = 1;
for (int i=0; i < lenP; i++)
{
if (tex1Dfetch(texT,startIndex+i) != shaP[i]) fMatch = 0;
}
if (fMatch) atomicMin(pFound, startIndex);
}
我想要做的是将文本放入共享内存块,如问题的其余部分所述,而不是将文本保留在纹理内存中以用于更高版本。
答案 0 :(得分:2)
我不确定这个问题是否有意义。您可以在运行时动态调整共享分配内存的大小,如下所示:
__global__ void kernel()
{
extern __shared__ int buffer[];
....
}
kernel<<< gridsize, blocksize, buffersize >>>();
但是内核开头的缓冲区内容是未定义的。您必须在内核中设计一个方案,以便从全局内存加载您想要的重叠,以确保您的模式匹配可以按照您的意愿工作。
答案 1 :(得分:1)
重叠共享内存不好,线程每次想要访问共享内存中的相同地址时都必须进行同步(尽管在架构&gt; = 2.0中已经减轻了这一点)。
我想到的最简单的想法是复制你想要重叠的文本部分。
而不是从精确的chuncks中读取全局内存:
AAAA BBBB CCCC DDDD EEEE
重读:
AAAA BBBB CCCC CCCC DDDD EEEEE
答案 2 :(得分:1)
没有。共享内存在块中的线程之间共享,并且只能由分配给它的块访问。您不能拥有可用于两个不同块的共享内存。
据我所知,共享内存实际上驻留在多处理器上,而一个线程只能从运行它的多处理器访问共享内存。所以这是一个物理限制。 (我猜如果两个块驻留在一个mp上,一个块的线程可能无法预测地访问分配给另一个块的共享内存)。
请记住,您需要将数据从全局内存显式复制到共享内存。将字符串的重叠区域复制到非重叠的共享内存是一件简单的事情。
我认为在您需要的地方获取数据是开发CUDA程序所需的大部分工作。我的指导是你从一个解决问题的版本开始,而不首先使用任何共享内存。为了实现这一点,您将解决重叠问题,并且共享内存实现将很容易!
编辑2
答案被标记为正确后
__global__ void gpuSearchTexSha(int lenT, int lenP, int *pFound)
{
extern __shared__ char* shared;
char* shaP = &shared[0];
char* shaT = &shared[lenP];
//copy pattern into shaP in parallel
if(threadIdx.x < lenP)
shaP[threadIdx.x] = tex1Dfetch(texP,threadIdx.x);
//determine texT start and length for this block
blockStartIndex = blockIdx.x * gridDim.x/lenT;
lenS = gridDim.x/lenT + lenP - 1;
//copy text into shaT in parallel
shaT[threadIdx.x] = tex1Dfetch(texT,blockStartIndex + threadIdx.x);
if(threadIdx.x < lenP)
shaP[blockDim.x + threadIdx.x] = text1Dfetch(texT,blockStartIndex + blockDim.x + threadIdx.x)
__syncthreads();
//We have one pattern in shaP for each thread in the block
//We have the necessary portion of the text (with overlaps) in shaT
int fMatch = 1;
for (int i=0; i < lenP; i++)
{
if (shaT[threadIdx.x+i] != shaP[i]) fMatch = 0;
}
if (fMatch) atomicMin(pFound, blockStartIndex + threadIdx.x);
}
主要说明:
lenP + lenS
(其中lenS是您的blocksize + patternlength
)