my-page

others

一个指令流控制多个数据流的处理器叫做 SIMD 处理器。SIMT 是 NVIDIA 公司提出的一个术语,指的是一种单指令多线程(Single Instruction Multiple Thread)的并行计算架构。SIMT 架构允许多个线程同时执行相同的指令,但每个线程可以处理不同的数据。这种架构在 GPU 中被广泛使用,可以大大提高并行计算的效率。

SIMD 带来了高速的运算,但可能需要更广泛的上下游修改,SIMT 则更容易编程和维护。

CUDA就是一种SIMT架构。

OpenMP: 跨平台共享内存方式的多线程并发的编程接口。

RDMA: Remote Direct Memory Access,远程直接内存访问,是一种允许计算机直接访问另一个计算机内存的技术,绕过操作系统和CPU的干预,从而实现更高效的数据传输。

CPU

CPU 将数据缓存到L1/L2/L3 Cache中,Cache是CPU内部的高速缓存SRAM(Static Random-Access Memory),MEMORY是外部的DRAM(Dynamic Random-Access Memory)。 L1 Cache速度最快但容量最小,L3 Cache速度较慢但容量较大。注意时间局限性和空间局限性(Temporal locality and spatial locality)。 优化方法:

GPU

CUDA开发要注意的问题:

alt text

How to write a+b?

__global__ void vecadd(double *a, double *b, double *c, int n) {
    // get global thread ID
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    // check if within bounds
    if (i < n) {
        c[i] = a[i] + b[i];
    }
}

对于以上代码中的blockIdx.xblockDim.xthreadIdx.x,它们是CUDA中的内置变量,用于计算每个线程的全局ID。

以上block、thread和kernel,grid的关系又是:grid由多个block组成,每个block由多个thread组成,kernel是执行在GPU上的函数。一个kernel对应的是一个grid。

SIMT

c = flag?a:b;
if (flag) c = a;

以上两种情况是比较快的

Tips

kernel launch

kernel<<<block_num, block_size>>>(args);
// CPU code: CPU继续执行其他任务
...
// CPU显式等待GPU完成
cudaDeviceSynchronize(); // 等待GPU完成

注意看,可以调参,block_num和block_size的选择会影响性能。一般来说,block_size应该是线程束大小(32)的倍数,以充分利用GPU的并行计算能力。

memory architecture

比如说,A100 GPU的内存架构

alt text

优化:能放L1 Cache的就放L1 Cache

memory coalescing(内存合并)

memory coalescing(内存合并)是指在GPU中,当多个线程访问连续的内存地址时,GPU可以将这些访问合并成一个单一的内存事务,从而提高内存访问效率。

比如说T1访问地址A,T2访问地址A+4,T3访问地址A+8,T4访问地址A+12,如果这些线程同时访问这些地址,GPU可以将这些访问合并成一个单一的内存事务,从而提高内存访问效率。

Load efficiency = used memory / total accessed memory

fat kernel: 每个线程访问一个元素,连续的线程访问连续的内存地址,这样可以实现内存合并,提高内存访问效率。

banks and shared memory

bank: GPU中的共享内存被划分为多个内存银行(memory banks),每个内存银行可以同时处理一个访问请求。当多个线程同时访问同一个内存银行中的不同地址时,就会发生banks conflict(银行冲突),导致性能下降。

操作和实现

避免atomic operation,原子操作会导致性能下降,因为它们需要锁定内存位置以确保数据的一致性。但是shared memory中的原子操作相对较快. 可以使用的libraries:

P.S. 有时候PyTorch直接使用也很快,因为它底层已经使用了这些库进行优化了。

CPU-GPU communication 和 软流水线

//TODO: https://www.bilibili.com/video/BV1424y1i7xe?spm_id_from=333.1387.collection.video_card.click software pipelining(软流水线)是一种优化技术,旨在提高CPU和GPU之间的通信效率。通过重叠CPU和GPU的计算和数据传输,可以减少等待时间,提高整体性能。

// initialize data on CPU : 350ms
//
void compute(){
    for(int i = 0; i < ARRSZ; ++i) {
        ++bin[arr[i]];
    }
}

//atomic : 6s, 因为每个线程都需要锁定内存位置以确保数据的一致性,导致性能下降。
void compute() {
    #pragma omp parallel for num_threads(40)
    for(int i = 0; i < ARRSZ; ++i) {
        #pragma omp atomic
        ++bin[arr[i]];
    }
}

//
void compute() {
    #pragma omp parallel for num_threads(40)
    for(int t = 0; t < 40; ++t) {
        int tmp_bin[256] = {0}; // 每个线程维护一个私有的临时bin

    }
}

用native GPU来的话:

__global__ void compute(int *arr, int *bin, int arr_sz) {
    int idx = blockIdx.x * blockDim.x + threadIdx.x;

MPI message passing interface

消息传递接口,是一种用于分布式计算的通信协议和编程模型。MPI允许不同计算节点之间进行通信和数据交换,使得分布式计算成为可能。