性能优化求助,shared memory 问题

youleelove 2009-06-25 02:14:18
现在的情况是:每个block内16X16线程,每个线程取上下左右四个值来处理,所以shared memory要读18X18。

我打算让四个边框上的线程来读取shared memory里的边框上的数据,但是这样要用到四个条件判断,if(tx==0),if(ty==0). if(tx == blocksize-1), if(ty = blocksize-1).

但是代码跑起来后结果不对,不知道为何错误. 同时觉得应该有更好的办法解决shared memory的读入问题,求助版上的高手.
下面是未经优化的代码:
__global__ void Laplace_d (float *A, float *B, int *N_t){

int tx = threadIdx.x; int ty = threadIdx.y;

int j = blockIdx.x * blockDim.x + tx;
int i = blockIdx.y * blockDim.y + ty;
int index, left, right, top, bottom;
int N=*N_t;

index = i*N +j;
left = i*N+ j-1;
right = i*N+ j+1;
top = (i-1)*N +j;
bottom = (i+1)*N+j;
if(i>0 && i<N-1 && j>0 && j<N-1){
B[index]=0.25*( A[left]+A[right]+A[top]+A[bottom])*0.9+0.1*B[index];
}
}
...全文
153 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
youleelove 2009-06-29
  • 打赏
  • 举报
回复
sigh~~~,结果反而慢了
youleelove 2009-06-29
  • 打赏
  • 举报
回复
程序搞定,结果没有错误,Cyrosly谢谢谢谢谢谢,哈哈。
texture < float, 1, cudaReadModeElementType> coalesed;
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();

__global__
void Laplace_d(float* D,int* N)
{

int tidx=blockDim.x*blockIdx.x+threadIdx.x;
int tidy=blockDim.y*blockIdx.y+threadIdx.y;
const int pitch=*N;
const int gloc=pitch*tidy+tidx;

__shared__ float smem[BLOCK_SIZE+2][BLOCK_SIZE+2];

int sidx=threadIdx.x+1;
int sidy=threadIdx.y+1;
smem[sidy][sidx]=tex1Dfetch(coalesed,gloc);
if(threadIdx.x==0){
smem[sidy][0 ]=tex1Dfetch(coalesed,gloc-1 ); //不需要担心索引越界,因为线型纹理在索引超出范围后会返回0,对结果没有影响
smem[sidy][BLOCK_SIZE+1]=tex1Dfetch(coalesed,gloc+BLOCK_SIZE);
}
if(threadIdx.y==0){
smem[0][sidx]=tex1Dfetch(coalesed,gloc-pitch);
smem[BLOCK_SIZE+1][sidx]=tex1Dfetch(coalesed,gloc+__mul24(pitch,BLOCK_SIZE));
}
__syncthreads();


if(tidx > 0 && tidx < pitch-1 && tidy > 0 && tidy < pitch -1){//之前的代码忘记了边界情况,后来改正了
D[gloc]=0.25*0.9*(smem[sidy][sidx-1]+smem[sidy][sidx+1]+smem[sidy-1][sidx]+smem[sidy+1][sidx])+0.1*smem[sidy][sidx];
}

}

最后附上调用函数的代码
while (k<ITERATIONS){

cudaBindTexture(0,&coalesed, device2,&channelDesc,size);
Laplace_d<<<dimGrid, dimBlock>>>(device1,n);
cudaUnbindTexture(&coalesed);

cudaBindTexture(0,&coalesed, device1,&channelDesc,size);
Laplace_d<<<dimGrid, dimBlock>>>(device2,n);
cudaUnbindTexture(&coalesed);
k+=2;
}
dtx08 2009-06-29
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 Cyrosly 的回复:]
引用 15 楼 dtx08 的回复:

引用 13 楼 Cyrosly 的回复:
还要加上最后一句SWAP()交换SRC和DST


敢问Cryosly是如何在devise中实现SWAP()的?


外循环不是在GPU上的
[/Quote]
这个我自然知道。你是用cudaMemcpy吗?我用的是cudaMemcpy(fromdevicetodevice)测试了下,这样挪移的成本完全抵消了texture的速度。你有快的吗?能否把代码写出来了?
Cyrosly 2009-06-28
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 dtx08 的回复:]
引用 13 楼 Cyrosly 的回复:
还要加上最后一句SWAP()交换SRC和DST



敢问Cryosly是如何在devise中实现SWAP()的?
[/Quote]

外循环不是在GPU上的
dtx08 2009-06-28
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 Cyrosly 的回复:]
还要加上最后一句SWAP()交换SRC和DST
[/Quote]

敢问Cryosly是如何在devise中实现SWAP()的?
dtx08 2009-06-28
  • 打赏
  • 举报
回复
敢问Cryosly是如何在devise中实现SWAP()的?
Cyrosly 2009-06-26
  • 打赏
  • 举报
回复
还要加上最后一句SWAP()交换SRC和DST
Cyrosly 2009-06-26
  • 打赏
  • 举报
回复
哎,还不明白那我就写出来

while(k<ITERATIONS){
bind_texture(tex,data[SRC]);
laplace_solver(data[DST],N);
++k;
}
Cyrosly 2009-06-25
  • 打赏
  • 举报
回复


#define DIMX 16
#define DIMY 16

//用纹理避免边界元素的非合并访问
//B :D
//A :绑定到纹理coalesed
//N_t:F

__global__
void laplace(float* D,const float* F,const float weight)
{
int tidx=__mul24(blockDim.x,blockIdx.x)+threadIdx.x;
int tidy=__mul24(blockDim.y,blockIdx.y)+threadIdx.y;
const int pitch=__mul24(gridDim.x,blockDim.x);
const int gloc=__mul24(pitch,tidy)+tidx;

__shared__ float smem[DIMY+2][DIMX+2];

tidx=threadIdx.x+1;
tidy=threadIdx.y+1;
smem[tidy][tidx]=tex1Dfetch(coalesed,gloc);
if(threadIdx.x==0){
smem[tidy][0 ]=tex1Dfetch(coalesed,gloc-1 ); //不需要担心索引越界,因为线型纹理在索引超出范围后会返回0,对结果没有影响
smem[tidy][DIMX+1]=tex1Dfetch(coelesed,gloc+DIM);
}
if(threadIdx.y==0){
smem[0 ][tidx]=tex1Dfetch(coelesed,gloc-pitch);
smem[DIMY+1][tidx]=tex1Dfetch(coalesed,gloc+__mul24(pitch,DIMY));
} __syncthreads();

D[gloc]=0.25f*weight*(smem[tidy][tidx-1]+smem[tidy][tidx+1]+smem[tidy-1][tidx]+smem[tidy+1][tidx])+(1.f-weight)*F[gloc];
}

  • 打赏
  • 举报
回复
没看到你的错误代码,估计问题如下:
1)每次读取块要和上行读取块/左边读取块没重合(该有一个数据重叠的)?
2)在读取地方if?应该是在计算地方用if判断的.
3)地址关系的对应不正确?

建议线程改为18x18线程,但计算结果还是按16x16分割.这样更方便些.
Cyrosly 2009-06-25
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 youleelove 的回复:]
回Cyrosly:
我需要在主函数里这样进行调用:
C/C++ codewhile (k<ITERATIONS){
Laplace_h(cpu_data2, cpu_data,N);
Laplace_h(cpu_data, cpu_data2,N);
k+=2;
}


所以这里绑定成texture 貌似行不通,我对texture不太懂,正在看资料。
[/Quote]
texture可以的
  • 打赏
  • 举报
回复
补充说明:
A的坐标变量[j][i],范围是0<->N-1.
sdata的坐标变量[ty][tx],范围是0<->B+1.
B的坐标变量[j][i],范围是1<->N-2.
要计算的点的坐标变量[y][x],范围是0<->B-1.

启动时的数据分块按要计算的点的范围分成BxB的块.
  • 打赏
  • 举报
回复
试试下面,没调试过哦.
启动时block数是((N-2)/BLOCKSIZE+1,(N-2)/BLOCKSIZE+1),线程数是(BLOCKSIZE+2,BLOCKSIZE+2).

__global__ void Laplace_d (float *A, float *B, int *N_t){

int tx = threadIdx.x; int ty = threadIdx.y;
int x = tx - 1; int y = ty - 1;

int j = blockIdx.x * BLOCK_SIZE + tx;
int i = blockIdx.y * BLOCK_SIZE + ty;
int index;

int N=*N_t;

index = i*N +j;

__shared__ float sdata[BLOCK_SIZE+2][BLOCK_SIZE+2];
if((i<=N-1)&&(j<=N-1)){
sdata[ty][tx] = A[index];
}
__syncthreads();

if((i<N-1)&&(j<N-1)){
if((x>=0)&&(y>=0)&(x<BLOCK_SIZE)&&(y<BLOCK_SIZE)){
B[index]=0.25*(sdata[ty-1][tx]+sdata[ty+1][tx]+sdata[ty][tx-1]+sdata[ty][tx+1])*0.9+0.1*sdata[ty][tx];
}
}
}
youleelove 2009-06-25
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 youleelove 的回复:]
回Cyrosly:
我需要在主函数里这样进行调用:C/C++ codewhile(k<ITERATIONS){
Laplace_h(cpu_data2, cpu_data,N);
Laplace_h(cpu_data, cpu_data2,N);
k+=2;
}
所以这里绑定成texture 貌似行不通,我对texture不太懂,正在看资料。
[/Quote]
代码错了,搞成CPU的了,下面是kernel的:
while (k<ITERATIONS){
Laplace_d<<<dimGrid, dimBlock>>>(device1, device2,n);
Laplace_d<<<dimGrid, dimBlock>>>(device2, device1,n);
k+=2;
}
youleelove 2009-06-25
  • 打赏
  • 举报
回复
回Cyrosly:
我需要在主函数里这样进行调用:
while (k<ITERATIONS){
Laplace_h(cpu_data2, cpu_data,N);
Laplace_h(cpu_data, cpu_data2,N);
k+=2;
}

所以这里绑定成texture 貌似行不通,我对texture不太懂,正在看资料。
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 l7331014 的回复:]
16x16计算14x14也行,但gmem读取时不对齐了,那个更好些,只有试验了.
[/Quote]

有些没考虑仔细.请无视.呵呵.
  • 打赏
  • 举报
回复
16x16计算14x14也行,但gmem读取时不对齐了,那个更好些,只有试验了.
youleelove 2009-06-25
  • 打赏
  • 举报
回复
//I did a new version and this one works, so any comments are welcome. 
__global__ void Laplace_d (float *A, float *B, int *N_t){

int tx = threadIdx.x; int ty = threadIdx.y;

int j = blockIdx.x * blockDim.x + tx;
int i = blockIdx.y * blockDim.y + ty;
int index;

int N=*N_t;

index = i*N +j;

//read data from global memory to shared memory
__shared__ float sdata[BLOCK_SIZE][BLOCK_SIZE];
sdata[ty][tx] = A[index];
__syncthreads();

if(i>0 && i<N-1 && j>0 && j<N-1){
float left = 0, right =0, top = 0, bottom =0;

//top
if(ty > 0)
top= sdata[ty-1][tx];
else top = A[index-N];

//left
if(tx > 0)
left = sdata[ty][tx-1];
else left = A[index-1];

//right
if(tx < BLOCK_SIZE-1)
right = sdata[ty][tx+1];
else right = A[index+1];

//bottom
if(ty < BLOCK_SIZE-1)
bottom = sdata[ty+1][tx];
else bottom = A[index+N];

B[index]=0.25*( left+right+top+bottom)*0.9+0.1*sdata[ty][tx];
}
}
youleelove 2009-06-25
  • 打赏
  • 举报
回复
能用一小段代码演示下怎么用18X18 来处理16X16的数据么?如果18X18的block size的话,那么就达不到full occupancy了吧?用16X16的block来处理14X14的数据呢?
 针对数据库的启动和关闭、控制文件与数据库初始化、参数及参数文件、数据字典、内存管理、Buffer Cache与Shared Pool原理、重做、回滚与撤销、等待事件、性能诊断与SQL优化等几大Oracle热点主题,本书从基础知识入手,深入研究相关技术,并结合性能调整及丰富的诊断案例,力图将Oracle知识全面、系统、深入地展现给读者。   本书给出了大量取自实际工作现场的实例,在分析实例的过程中,兼顾深度与广度,不仅对实际问题的现象、产生原因和相关的原理进行了深入浅出的讲解,更主要的是,结合实际应用环境,提供了一系列解决问题的思路和方法,包括详细的操作步骤,具有很强的实战性和可操作性,适用于具备一定数据库基础、打算深入学习Oracle技术的数据库从业人员,尤其适用于入门、进阶以及希望深入研究Oracle技术的数据库管理人员。 第1章 数据库的启动和关闭 1 1.1 数据库的启动 1 1.1.1 启动数据库到NOMOUNT状态的过程 2 1.1.2 启动数据库到MOUNT状态 18 1.1.3 启动数据库OPEN阶段 26 1.2 数据库的访问 37 1.2.1 客户端的TNSNAMES.ORA文件配置 37 1.2.2 服务器端的监听器文件listener.ora配置 39 1.2.3 通过不同服务器名对数据库的访问 41 1.2.4 动态监听器注册服务 42 1.3 数据库的关闭 46 1.3.1 数据库关闭的步骤 46 1.3.2 几种关闭方式的对比 48 第2章 控制文件与数据库初始化 51 2.1 控制文件的内容 51 2.2 SCN 53 2.2.1 SCN的定义 53 2.2.2 SCN的获取方式 53 2.2.3 SCN的进一步说明 54 2.3 检查点(Checkpoint) 57 2.3.1 检查点(Checkpoint)的工作原理 57 2.3.2 常规检查点与增量检查点 59 2.3.3 LOG_CHECKPOINT_TO_ALERT参数 63 2.3.4 控制文件与数据文件头信息 64 2.3.5 数据库的启动验证 66 2.3.6 使用备份的控制文件 70 2.3.7 FAST_START_MTTR_TARGET 71 2.3.8 关于检查点执行的案例 74 2.3.9 Oracle 10g自动检查点调整 75 2.3.10 检查点信息及恢复起点 78 2.3.11 正常关闭数据库的状况 78 2.3.12 数据库异常关闭的情况 80 2.3.13 数据库并行恢复案例一则 82 2.3.14 判断一个死事务的恢复进度 85 2.4 数据库的初始化 86 2.4.1 bootstrap$及数据库初始化过程 86 2.4.2 bootstrap$的定位 88 2.4.3 Oracle中独一无二的Cache对象 89 2.4.4 Oracle数据库的引导 91 2.4.5 系统对象与bootstrap$ 92 2.4.6 bootstrap$的重要性 94 2.4.7 BBED工具的简要介绍 95 2.4.8 坏块的处理与恢复 97 第3章 参数及参数文件 103 3.1 初始化参数的分类 103 3.1.1 推导参数(Derived Parameters) 103 3.1.2 操作系统依赖参数 104 3.1.3 可变参数 104 3.1.4 初始化参数的获取 105 3.2 参数文件 107 3.2.1 PFILE和SPFILE 108 3.2.2 获取参数的视图 110 3.2.3 SPFILE的创建 111 3.2.4 SPFILE的搜索顺序 112 3.2.5 使用PFILE/SPFILE启动数据库 112 3.2.6 修改参数 113 3.2.7 解决SPFILE参数修改错误 118 3.2.8 重置SPFILE中设置的参数 120 3.2.9 判断是否使用了SPFILE 120 3.2.10 SPFILE的备份与恢复 121 3.2.11 Oracle 11g参数文件恢复 127 3.2.12 如何设置Events事件 128 3.2.13 导出SPFILE文件 129 3.3 诊断案例之一:参数文件 131 3.3.1 登录系统检查告警日志文件 131 3.3.2 尝试重新启动数据库 132 3.3.3 检查数据文件 132 3.3.4 MOUNT数据库,检查系统参数 133 3.3.5 检查参数文件 133 3.3.6 再次检查alert文件 134 3.3.7 修正PFILE 135 3.3.8 启动数据库 135 3.4 诊断案例之二:RAC环境参数文件 135 3.4.1 数据库资源异常 135 3.4.2 问题的发现 136 3.4.3 参数文件问题的解决 137 第4

353

社区成员

发帖
与我相关
我的任务
社区描述
CUDA高性能计算讨论
社区管理员
  • CUDA高性能计算讨论社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧