DCU异构程序——带宽测试

目录

一、概述

二、程序实现

三、编译运行


一、概述

HIP属于显式编程模型,需要在程序中明确写出并行控制语句,包括数据传输核函数启动等。核函数是运行在DCU上的函数,在CPU端运行的部分称为主机端(主要是执行管理和启动),DCU端运行的部分称为设备端(用于执行计算)。大概的流程如下图:
HIP程序流程

①主机端将需要并行计算的数据通过hipMemcpy()传递给DCU(将CPU存储的内容传递给DCU的显存);

②调用核函数启动函数hipLaunchKernelGGL()启动DCU,开始执行计算;

③设备端将计算好的结果数据通过hipMemcpy()从DCU复制回CPU。

hipMemcpy()是阻塞式的,数据复制完成后才可以执行后续的程序;hipLanuchKernelGGL()是非阻塞式的,执行完后程序继续向后执行,但是在Kernel没有计算完成之前,最后一个hipMemcpy()是不会开始的,这是由于HIP的Stream机制。

二、程序实现

下面是对带宽测试的具体实现,bandwidthcpp:

cpp 复制代码
#include <stdio.h>
#include <assert.h>
#include <hip/hip_runtime.h>

inline hipError_t checkhip(hipError_t result)
{
#if defined(DEBUG) || defined(_DEBUG)
    if(result != hipSuccess)
    {
        fprintf(stderr, "hip Runtime Error: %s\n", hipGetErrorString(result));
        assert(result == hipSuccess);
    }
#endif
    return result;
}

template<typename T>
__global__ void offset(T *a, int s)
{
    int i = blockDim.x * blockIdx.x + threadIdx.x + s;
    a[i] = a[i] + 1;
}

template<typename T>
__global__ void stride(T *a, int s)
{
    int i = (blockDim.x * blockIdx.x + threadIdx.x) * s;
    a[i] = a[i] + 1;
}

template<typename T>
void runTest(int deviceId, int nMB)
{
    int blockSize = 256;
    float ms;

    T *d_a;
    hipEvent_t startEvent, stopEvent;

    int n = nMB * 1024 * 1024 / sizeof(T);

    checkhip(hipMalloc(&d_a, n * 33 * sizeof(T)));
    checkhip(hipEventCreate(&startEvent));
    checkhip(hipEventCreate(&stopEvent));

    printf("Offset, Bandwith (GB/s): \n");

    offset<<<n / blockSize, blockSize>>>(d_a, 0);

    for(int i = 0; i <= 32; i++)
    {
        checkhip(hipMemset(d_a, 0, n * sizeof(T)));
        checkhip(hipEventRecord(startEvent, 0));
        offset<<<n / blockSize, blockSize>>>(d_a, i);
        checkhip(hipEventRecord(stopEvent, 0));
        checkhip(hipEventSynchronize(stopEvent));

        checkhip(hipEventElapsedTime(&ms, startEvent, stopEvent));
        printf("%d, %f\n", i, 2 * nMB / ms);
    }

    printf("\n Stride, Bandwidth (GB/s):\n");

    stride<<<n / blockSize, blockSize>>>(d_a, 1);

    for(int i = 1; i <= 32; i++)
    {
        checkhip(hipMemset(d_a, 0, n * sizeof(T)));
        checkhip(hipEventRecord(startEvent, 0));
        stride<<<n / blockSize, blockSize>>>(d_a, i);
        checkhip(hipEventRecord(stopEvent, 0));
        checkhip(hipEventSynchronize(stopEvent));

        checkhip(hipEventElapsedTime(&ms, startEvent, stopEvent));
        printf("%d, %f\n", i, 2 * nMB / ms);
    }

    checkhip(hipEventDestroy(startEvent));
    checkhip(hipEventDestroy(stopEvent));
    hipFree(d_a);
}


int main(int argc, char *argv[])
{
    int nMB = 128;
    int deviceId = 0;
    bool bFp64 = false;

    for(int i = 1; i < argc; i++)
    {
        if(!strncmp(argv[i], "dev=", 4))
        {
            deviceId = atoi((char *)(&argv[i][1]));
        }
        else if(!strcmp(argv[i], "fp64"))
        {
            bFp64 = true;
        }
    }

    hipDeviceProp_t prop;

    checkhip(hipSetDevice(deviceId));
    checkhip(hipGetDeviceProperties(&prop, deviceId));
    printf("Device: %s\n", prop.name);
    printf("Transfer size (MB): %d\n", nMB);
    printf("%s Precision\n", bFp64 ? "Double":"Single");

    if(bFp64)
    {
        runTest<double>(deviceId, nMB);
    }
    else
    {
        runTest<float>(deviceId, nMB);
    }
    return 0;
}

三、编译运行

HIP程序采用hipcc编译。

运行结果:

相关推荐
菜鸟555555 分钟前
图论:Floyd算法
算法·图论
Minecraft红客6 分钟前
C++小游戏荒芜的城堡
c++·游戏·娱乐
uzong5 小时前
面试官:Redis中的 16 库同时发送命令,服务端是串行执行还是并行执行
后端·面试·架构
呼啦啦啦啦啦啦啦啦5 小时前
常见的排序算法
java·算法·排序算法
The Open Group6 小时前
英特尔公司Darren Pulsipher 博士:以架构之力推动政府数字化转型
大数据·人工智能·架构
胡萝卜3.06 小时前
数据结构初阶:排序算法(一)插入排序、选择排序
数据结构·笔记·学习·算法·排序算法·学习方法
地平线开发者6 小时前
LLM 中 token 简介与 bert 实操解读
算法·自动驾驶
scx201310046 小时前
20250814 最小生成树和重构树总结
c++·算法·最小生成树·重构树
阿巴~阿巴~6 小时前
冒泡排序算法
c语言·开发语言·算法·排序算法
散1127 小时前
01数据结构-交换排序
数据结构·算法