CUDA:共享内存和并行性较差
我试图在这个内核函数中利用共享内存,但是性能没有我预期的那么好。这个函数在我的应用程序中被调用了很多次(大约1000次或更多),所以我想利用共享内存来避免内存延迟。但显然有些问题,因为我使用共享内存后,我的应用程序变得非常慢。CUDA:共享内存和并行性较差,cuda,parallel-processing,shared-memory,Cuda,Parallel Processing,Shared Memory,我试图在这个内核函数中利用共享内存,但是性能没有我预期的那么好。这个函数在我的应用程序中被调用了很多次(大约1000次或更多),所以我想利用共享内存来避免内存延迟。但显然有些问题,因为我使用共享内存后,我的应用程序变得非常慢。 这是内核: __global__ void AndBitwiseOperation(int* _memory_device, int b1_size, int* b1_memory, int* b2_memory){ int j = 0; // index GPU -
这是内核:
__global__ void AndBitwiseOperation(int* _memory_device, int b1_size, int* b1_memory, int* b2_memory){
int j = 0;
// index GPU - Transaction-wise
unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;
unsigned int tid = threadIdx.x;
// shared variable
extern __shared__ int shared_memory_data[];
extern __shared__ int shared_b1_data[];
extern __shared__ int shared_b2_data[];
// copy from global memory into shared memory and sync threads
shared_b1_data[tid] = b1_memory[tid];
shared_b2_data[tid] = b2_memory[tid];
__syncthreads();
// AND each int bitwise
for(j = 0; j < b1_size; j++)
shared_memory_data[tid] = (shared_b1_data[tid] & shared_b2_data[tid]);
// write result for this block to global memory
_memory_device[i] = shared_memory_data[i];
}
void Bitmap::And(const Bitmap &b1, const Bitmap &b2)
{
int* _memory_device;
int* b1_memory;
int* b2_memory;
int b1_size = b1.getIntSize();
// allocate memory on GPU
(cudaMalloc((void **)&b1_memory, _memSizeInt * SIZE_UINT));
(cudaMalloc((void **)&b2_memory, _memSizeInt * SIZE_UINT));
(cudaMalloc((void **)&_memory_device, _memSizeInt * SIZE_UINT));
// copy values on GPU
(cudaMemcpy(b1_memory, b1._memory, _memSizeInt * SIZE_UINT, cudaMemcpyHostToDevice ));
(cudaMemcpy(b2_memory, b2._memory, _memSizeInt * SIZE_UINT, cudaMemcpyHostToDevice ));
(cudaMemcpy(_memory_device, _memory, _memSizeInt * SIZE_UINT, cudaMemcpyHostToDevice ));
dim3 dimBlock(1, 1);
dim3 dimGrid(1, 1);
AndBitwiseOperation<<<dimGrid, dimBlock>>>(_memory_device, b1_size, b1_memory, b2_memory);
// return values
(cudaMemcpy(_memory, _memory_device, _memSizeInt * SIZE_UINT, cudaMemcpyDeviceToHost ));
// Free Memory
(cudaFree(b1_memory));
(cudaFree(b2_memory));
(cudaFree(_memory_device));
}
\uuuuu全局\uuuuuu无效和按位操作(int*\u内存设备、int b1\u大小、int*b1\u内存、int*b2\u内存){
int j=0;
//索引GPU-事务智能
无符号整数i=blockIdx.x*blockDim.x+threadIdx.x;
unsigned int tid=threadIdx.x;
//共享变量
外部共享内存数据[];
外部共享内部共享数据[];
外部共享内部共享数据[];
//从全局内存复制到共享内存并同步线程
共享_b1_数据[tid]=b1_内存[tid];
共享的b2_数据[tid]=b2_内存[tid];
__同步线程();
//每个整数按位计算
对于(j=0;j
共享变量声明为extern,因为我不知道b1和b2的大小,因为它们取决于我只能在运行时知道的客户数量(但两者的大小始终相同)。这是我如何称呼内核的:
__global__ void AndBitwiseOperation(int* _memory_device, int b1_size, int* b1_memory, int* b2_memory){
int j = 0;
// index GPU - Transaction-wise
unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;
unsigned int tid = threadIdx.x;
// shared variable
extern __shared__ int shared_memory_data[];
extern __shared__ int shared_b1_data[];
extern __shared__ int shared_b2_data[];
// copy from global memory into shared memory and sync threads
shared_b1_data[tid] = b1_memory[tid];
shared_b2_data[tid] = b2_memory[tid];
__syncthreads();
// AND each int bitwise
for(j = 0; j < b1_size; j++)
shared_memory_data[tid] = (shared_b1_data[tid] & shared_b2_data[tid]);
// write result for this block to global memory
_memory_device[i] = shared_memory_data[i];
}
void Bitmap::And(const Bitmap &b1, const Bitmap &b2)
{
int* _memory_device;
int* b1_memory;
int* b2_memory;
int b1_size = b1.getIntSize();
// allocate memory on GPU
(cudaMalloc((void **)&b1_memory, _memSizeInt * SIZE_UINT));
(cudaMalloc((void **)&b2_memory, _memSizeInt * SIZE_UINT));
(cudaMalloc((void **)&_memory_device, _memSizeInt * SIZE_UINT));
// copy values on GPU
(cudaMemcpy(b1_memory, b1._memory, _memSizeInt * SIZE_UINT, cudaMemcpyHostToDevice ));
(cudaMemcpy(b2_memory, b2._memory, _memSizeInt * SIZE_UINT, cudaMemcpyHostToDevice ));
(cudaMemcpy(_memory_device, _memory, _memSizeInt * SIZE_UINT, cudaMemcpyHostToDevice ));
dim3 dimBlock(1, 1);
dim3 dimGrid(1, 1);
AndBitwiseOperation<<<dimGrid, dimBlock>>>(_memory_device, b1_size, b1_memory, b2_memory);
// return values
(cudaMemcpy(_memory, _memory_device, _memSizeInt * SIZE_UINT, cudaMemcpyDeviceToHost ));
// Free Memory
(cudaFree(b1_memory));
(cudaFree(b2_memory));
(cudaFree(_memory_device));
}
void位图::And(常量位图和b1、常量位图和b2)
{
int*内存设备;
int*b1_存储器;
int*b2_存储器;
int b1_size=b1.getIntSize();
//在GPU上分配内存
(cudamaloc((void**)和b1_memory,_memSizeInt*SIZE_UINT));
(cudamaloc((void**)和b2_memory,_memSizeInt*SIZE_UINT));
(cudamaloc((void**)和内存设备,_memSizeInt*SIZE UINT));
//在GPU上复制值
(cudaMemcpy(b1_内存,b1._内存,_memSizeInt*SIZE_UINT,cudamemcpyhostodevice));
(cudaMemcpy(b2_内存,b2._内存,_memSizeInt*SIZE_UINT,cudamemcpyhostodevice));
(cudaMemcpy(_memory_device,_memory,_memSizeInt*SIZE_UINT,cudamemcpyhostodevice));
dim3 dimBlock(1,1);
dim3 dimGrid(1,1);
AND位操作(_内存_设备、b1_大小、b1_内存、b2_内存);
//返回值
(cudaMemcpy(_memory,_memory,_device,_memSizeInt*SIZE_UINT,cudaMemcpyDeviceToHost));
//空闲内存
(cudaFree(b1_内存));
(cudaFree(b2_存储器));
(cudaFree(存储设备));
}
b1和b2是位图,每个元素有4位。元素的数量取决于客户的数量。另外,我对内核的参数也有问题,因为如果我添加一些块或线程,AndBitwiseOperation()不会给出正确的结果。每个块只有一个块和一个线程,结果是正确的,但内核不是并行的。欢迎您的建议:)
谢谢在声明
外部共享数组时,还必须在内核调用中指定其大小
内核配置为:
>
Ns是外部共享数组的大小,默认为0
我认为您不能在内核中定义多个extern\uuuu共享\uuuu
数组。《编程指南》中的一个示例定义了单个extern\uuuuuuu共享\uuuuuuu
数组,并手动设置带有偏移量的数组:
extern __shared__ float array[];
__device__ void func() // __device__ or __global__ function
{
short* array0 = (short*)array;
float* array1 = (float*)&array0[128];
int* array2 = (int*)&array1[64];
}
在声明extern\uuuu共享\uuuuu
数组时,还必须在内核调用中指定其大小
内核配置为:
>
Ns是外部共享数组的大小,默认为0
我认为您不能在内核中定义多个extern\uuuu共享\uuuu
数组。《编程指南》中的一个示例定义了单个extern\uuuuuuu共享\uuuuuuu
数组,并手动设置带有偏移量的数组:
extern __shared__ float array[];
__device__ void func() // __device__ or __global__ function
{
short* array0 = (short*)array;
float* array1 = (float*)&array0[128];
int* array2 = (int*)&array1[64];
}
我并没有真正理解您的内核想要做什么
您应该阅读更多有关CUDA和GPU编程的信息。
我试图指出一些错误
共享内存(sm)应减少全局内存读取。
分析每个线程的全局内存(gm)读写操作
a。您读取全局内存两次,写入sm两次
B(忽略无意义的循环,不使用索引)您读取两次sn,写入一次sm
C你读一次sm,写一次gm
总的来说,你什么也得不到。您可以直接使用全局内存
使用所有线程在块索引“i”处写出一个值。
您应该只使用一个线程来写入此数据。
由多个线程输出相同的数据将被序列化是没有意义的
您使用循环,但根本不使用循环计数器
你在“tid”写,在“i”读
这个任务是开销
unsigned int tid = threadIdx.x;
多个区块的结果不可能正确,因为一个区块的tid=i
所有错误的索引都会导致使用多个块进行错误的计算
“我”的共享记忆从未被写过
_memory_device[i] = shared_memory_data[i];
我的假设您的内核应该做什么
/*
* Call kernel with x-block usage and up to 3D Grid
*/
__global__ void bitwiseAnd(int* outData_g,
const long long int inSize_s,
const int* inData1_g,
const int* inData2_g)
{
//get unique block index
const unsigned long long int blockId = blockIdx.x //1D
+ blockIdx.y * gridDim.x //2D
+ gridDim.x * gridDim.y * blockIdx.z; //3D
//get unique thread index
const unsigned long long int threadId = blockId * blockDim.x + threadIdx.x;
//check global unique thread range
if(threadId >= inSize_s)
return;
//output bitwise and
outData_g[thread] = inData1_g[thread] & inData2_g[thread];
}
我并没有真正理解您的内核想要做什么
您应该阅读更多有关CUDA和GPU编程的信息。
我试图指出一些错误
共享内存(sm)应减少全局内存读取。
分析每个线程的全局内存(gm)读写操作
a。您读取全局内存两次,写入sm两次
B(忽略无意义的循环,不使用索引)您读取两次sn,写入一次sm
C你读一次sm,写一次gm
总的来说,你什么也得不到。您可以直接使用全局内存
使用所有线程在块索引“i”处写出一个值。
您应该只使用一个线程来写入此数据。
输出相同的数据毫无意义