CUDA:共享内存和并行性较差

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 -

我试图在这个内核函数中利用共享内存,但是性能没有我预期的那么好。这个函数在我的应用程序中被调用了很多次(大约1000次或更多),所以我想利用共享内存来避免内存延迟。但显然有些问题,因为我使用共享内存后,我的应用程序变得非常慢。
这是内核:

__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”处写出一个值。 您应该只使用一个线程来写入此数据。
    输出相同的数据毫无意义