使用ROCm的HIP API向量加法程序

news2025/6/22 9:19:02

一、向量加法程序

Radeon Open Compute (ROCm) 是一个开源平台,用于加速高性能计算 (HPC) 和机器学习应用程序。它支持包括GPUs在内的多种硬件,并提供HIP (Heterogeneous-compute Interface for Portability) 作为CUDA代码的便捷转换工具。为了提供一个使用ROCm的实例,假设已经在符合要求的硬件上安装了ROCm环境。下面的例子是一个简单的向量加法程序,使用了ROCm的HIP API。

首先,需要编写 HIP 源代码,该代码之后可以被编译运行在 AMD GPU 上。可以创建一个名为 vector_add.cpp 的文件:

#include <hip/hip_runtime.h>
#include <iostream>

#define N 50000

__global__ void vector_add(float *out, float *a, float *b, int n) {
    int index = threadIdx.x + blockIdx.x * blockDim.x;
    if (index < n) {
        out[index] = a[index] + b[index];
    }
}

int main() {
    float *a, *b, *out;
    float *d_a, *d_b, *d_out;

    // 分配host内存
    a = (float*)malloc(sizeof(float) * N);
    b = (float*)malloc(sizeof(float) * N);
    out = (float*)malloc(sizeof(float) * N);

    // 初始化数据
    for (int i = 0; i < N; i++) {
        a[i] = float(i);
        b[i] = float(i);
    }

    // 分配device(GPU)内存
    hipError_t err;  
    err = hipMalloc((void**)&d_a, sizeof(float) * N);
    if (err != hipSuccess) {
        // 处理错误,比如打印错误信息并退出程序  
        fprintf(stderr, "hipMalloc failed: %s\n", hipGetErrorString(err));  
        exit(EXIT_FAILURE);  
    }
        
    err = hipMalloc((void**)&d_b, sizeof(float) * N);
    if (err != hipSuccess) {
        // 处理错误,比如打印错误信息并退出程序  
        fprintf(stderr, "hipMalloc failed: %s\n", hipGetErrorString(err));  
        exit(EXIT_FAILURE);  
    }

    err = hipMalloc((void**)&d_out, sizeof(float) * N);
    if (err != hipSuccess) {
        // 处理错误,比如打印错误信息并退出程序  
        fprintf(stderr, "hipMalloc failed: %s\n", hipGetErrorString(err));  
        exit(EXIT_FAILURE);  
    }

    // 将host数据复制到device(GPU)上
    err = hipMemcpy(d_a, a, sizeof(float) * N, hipMemcpyHostToDevice);
    if (err != hipSuccess) {
        // 处理错误,比如打印错误信息并退出程序  
        fprintf(stderr, "hipMemcpy failed: %s\n", hipGetErrorString(err));  
        exit(EXIT_FAILURE);  
    }

    err = hipMemcpy(d_b, b, sizeof(float) * N, hipMemcpyHostToDevice);
    if (err != hipSuccess) {
        // 处理错误,比如打印错误信息并退出程序  
        fprintf(stderr, "hipMemcpy failed: %s\n", hipGetErrorString(err));  
        exit(EXIT_FAILURE);  
    }

    // 执行kernel
    int blockSize = 256;
    int gridSize = (int)ceil((float)N/blockSize);
    hipLaunchKernelGGL(vector_add, dim3(gridSize), dim3(blockSize), 0, 0, d_out, d_a, d_b, N);

    // 将计算结果复制回host内存
    err = hipMemcpy(out, d_out, sizeof(float) * N, hipMemcpyDeviceToHost);
    if (err != hipSuccess) {
        // 处理错误,比如打印错误信息并退出程序  
        fprintf(stderr, "hipMemcpy failed: %s\n", hipGetErrorString(err));  
        exit(EXIT_FAILURE);  
    }

    // 验证结果
    for (int i = 0; i < N; i++) {
        if (out[i] != a[i] + b[i]) {
            std::cerr << "结果验证失败,索引 " << i << ", " << out[i] << " != " << a[i] + b[i] << std::endl;
            break;
        }
    }

    // 释放内存
    err = hipFree(d_a); 
    if (err != hipSuccess) {
        // 处理错误,比如打印错误信息并退出程序  
        fprintf(stderr, "hipFree failed: %s\n", hipGetErrorString(err));  
        exit(EXIT_FAILURE);  
    }

    err = hipFree(d_b); 
    if (err != hipSuccess) {
        // 处理错误,比如打印错误信息并退出程序  
        fprintf(stderr, "hipFree failed: %s\n", hipGetErrorString(err));  
        exit(EXIT_FAILURE);  
    }

    err = hipFree(d_out);
    if (err != hipSuccess) {
        // 处理错误,比如打印错误信息并退出程序  
        fprintf(stderr, "hipFree failed: %s\n", hipGetErrorString(err));  
        exit(EXIT_FAILURE);  
    }

    free(a); free(b); free(out);

    return 0;
}

接下来可以使用 hipcc 编译器来编译上述程序。hipcc 是一个包装好的编译器,用于将HIP源码编译为可以在准备好的AMD平台上运行的代码:

hipcc vector_add.cpp -o vector_add

编译成功后,可以运行生成的应用程序:

./vector_add

以上代码演示了如何使用HIP编写一个简单的GPU内核,其计算两个向量的逐元素加法。请确保在运行任何这些步骤之前,检查环境是否配置正确,ROCm是否与AMD GPU兼容,并且已正确安装。如果对ROCm更复杂的使用场景感兴趣,可以查看ROCm提供的示例和使用指南。

二、通义灵码

ROCm(Radeon Open Compute Platform)提供了HIP(Heterogeneous-Compute Interface for Portability)API,允许开发者编写高度可移植的代码,能够在AMD GPU和其他异构平台上运行。以下是一个使用HIP API编写的简单向量加法程序示例:

#include <hip/hip_runtime.h>
#include <iostream>

#define VECTOR_SIZE 1024  // 向量长度

// 定义向量加法的内核函数
__global__ void vectorAdd(float* A, float* B, float* C) {
    int idx = threadIdx.x + blockIdx.x * blockDim.x;
    if (idx < VECTOR_SIZE) {
        C[idx] = A[idx] + B[idx];
    }
}

int main() {
    float* h_A;  // 主机侧向量A
    float* h_B;  // 主机侧向量B
    float* h_C;  // 主机侧结果向量C(用于验证)

    float* d_A;  // 设备侧向量A
    float* d_B;  // 设备侧向量B
    float* d_C;  // 设备侧结果向量C

    size_t size = VECTOR_SIZE * sizeof(float);

    // 分配主机内存并初始化向量
    h_A = new float[VECTOR_SIZE];
    h_B = new float[VECTOR_SIZE];
    h_C = new float[VECTOR_SIZE];

    for (size_t i = 0; i < VECTOR_SIZE; ++i) {
        h_A[i] = static_cast<float>(i);
        h_B[i] = static_cast<float>(i * 2);
    }

    // 分配设备内存
    hipMalloc(&d_A, size);
    hipMalloc(&d_B, size);
    hipMalloc(&d_C, size);

    // 将主机内存数据复制到设备
    hipMemcpy(d_A, h_A, size, hipMemcpyHostToDevice);
    hipMemcpy(d_B, h_B, size, hipMemcpyHostToDevice);

    // 定义并启动内核
    dim3 blockSize(256);  // 每块256个线程
    dim3 gridSize((VECTOR_SIZE + blockSize.x - 1) / blockSize.x);  // 计算所需网格数
    vectorAdd<<<gridSize, blockSize>>>(d_A, d_B, d_C);

    // 将设备计算结果复制回主机
    hipMemcpy(h_C, d_C, size, hipMemcpyDeviceToHost);

    // 验证结果
    bool resultCorrect = true;
    for (size_t i = 0; i < VECTOR_SIZE; ++i) {
        if (h_C[i] != h_A[i] + h_B[i]) {
            resultCorrect = false;
            break;
        }
    }

    std::cout << "Vector addition test " << (resultCorrect ? "PASSED" : "FAILED") << std::endl;

    // 释放资源
    hipFree(d_A);
    hipFree(d_B);
    hipFree(d_C);
    delete[] h_A;
    delete[] h_B;
    delete[] h_C;

    return 0;
}

三、文心一言

HIP (Heterogeneous-compute Interface for Portability) 是一个用于简化在AMD GPU上编程的接口,它提供了类似于CUDA的编程模型,使得开发者可以更容易地将CUDA代码迁移到HIP上,以在AMD GPU上运行。

下面是一个简单的HIP程序示例,用于执行向量加法。请注意,这个示例假设你已经安装并配置了ROCm和HIP环境。

首先,你需要创建一个HIP源文件(例如,vector_add.hip),并写入以下代码:

#include <hip/hip_runtime.h>  
#include <hip/hip_vector_types.h>  
  
__global__ void vector_add(float* A, float* B, float* C, int N) {  
    int i = hipBlockIdx_x * hipBlockDim_x + hipThreadIdx_x;  
    if (i < N) {  
        C[i] = A[i] + B[i];  
    }  
}  
  
int main(void) {  
    const int N = 1 << 20; // 1M elements  
    const size_t size = N * sizeof(float);  
  
    // Allocate Unified Memory – accessible from CPU or GPU  
    float *A, *B, *C;  
    hipMallocManaged(&A, size);  
    hipMallocManaged(&B, size);  
    hipMallocManaged(&C, size);  
  
    // Initialize data on the host  
    for (int i = 0; i < N; i++) {  
        A[i] = 1.0f;  
        B[i] = 2.0f;  
    }  
  
    // Run kernel on 1M elements on the GPU  
    hipLaunchKernelGGL((vector_add), dim3(N/256, 1, 1), dim3(256, 1, 1), 0, 0, A, B, C, N);  
  
    // Wait for GPU to finish before accessing on host  
    hipDeviceSynchronize();  
  
    // Verify results  
    for (int i = 0; i < N; i++) {  
        if (C[i] != 3.0f) {  
            printf("Error at element %d: %f != 3.0f\n", i, C[i]);  
            return -1;  
        }  
    }  
  
    printf("Test PASSED\n");  
  
    // Free memory  
    hipFree(A);  
    hipFree(B);  
    hipFree(C);  
  
    return 0;  
}

在这个示例中,vector_add 是一个GPU内核函数,用于执行向量加法。main 函数中首先分配了统一内存(Unified Memory),这是一种HIP和ROCm支持的特性,允许CPU和GPU无缝地访问同一块内存区域。然后,初始化数据并调用HIP内核。最后,验证结果并释放内存。

编译这个程序,你需要使用hipcc编译器,它是专门为HIP设计的。编译命令可能类似于:

hipcc -o vector_add vector_add.hip

确保你的环境变量和路径已经配置好,以便hipcc可以找到ROCm和HIP相关的库和头文件。

运行编译后的程序:

./vector_add

如果一切正常,你应该会看到“Test PASSED”的输出,表示向量加法已经成功执行。

请注意,HIP和ROCm的API和功能可能会随着版本的更新而发生变化,因此请确保查阅最新的官方文档以获取最准确的信息。

四、讯飞星火

以下是一个使用ROCm的HIP API进行向量加法的程序示例:

#include <iostream>
#include <vector>
#include <hip/hip_runtime.h>

__global__ void vectorAdd(const float* A, const float* B, float* C, int numElements) {
    int i = blockDim.x * blockIdx.x + threadIdx.x;
    if (i < numElements) {
        C[i] = A[i] + B[i];
    }
}

int main() {
    int numElements = 50000;
    size_t size = numElements * sizeof(float);

    float* h_A = new float[numElements];
    float* h_B = new float[numElements];
    float* h_C = new float[numElements];

    for (int i = 0; i < numElements; ++i) {
        h_A[i] = static_cast<float>(i);
        h_B[i] = static_cast<float>(i * 2);
    }

    float* d_A = nullptr;
    float* d_B = nullptr;
    float* d_C = nullptr;

    hipMalloc((void**)&d_A, size);
    hipMalloc((void**)&d_B, size);
    hipMalloc((void**)&d_C, size);

    hipMemcpy(d_A, h_A, size, hipMemcpyHostToDevice);
    hipMemcpy(d_B, h_B, size, hipMemcpyHostToDevice);

    dim3 dimBlock(256);
    dim3 dimGrid((numElements + dimBlock.x - 1) / dimBlock.x);

    hipLaunchKernelGGL(vectorAdd, dimGrid, dimBlock, 0, 0, d_A, d_B, d_C, numElements);

    hipMemcpy(h_C, d_C, size, hipMemcpyDeviceToHost);

    for (int i = 0; i < numElements; ++i) {
        if (fabs(h_A[i] + h_B[i] - h_C[i]) > 1e-5) {
            std::cout << "Result verification failed at element " << i << std::endl;
            break;
        }
    }

    delete[] h_A;
    delete[] h_B;
    delete[] h_C;

    hipFree(d_A);
    hipFree(d_B);
    hipFree(d_C);

    return 0;
}

这个程序首先创建了三个大小为`numElements`的浮点数数组`h_A`、`h_B`和`h_C`,并将`h_A`和`h_B`的元素分别设置为连续的整数。然后,它使用HIP API分配设备内存并将主机数据复制到设备上。接下来,它定义了一个名为`vectorAdd`的CUDA内核函数,该函数将两个输入向量相加并将结果存储在输出向量中。最后,它将计算结果从设备复制回主机,并验证结果的正确性。如果结果验证失败,则输出错误信息。最后,它释放了所有分配的内存。

五、Kimi

ROCm(Radeon Open Compute)是一个开源的计算平台,旨在为AMD GPU提供高性能的计算能力。HIP(Heterogeneous-compute Interface for Portability)是ROCm的一个C/C++运行时API,它允许开发者编写可在多种计算设备上运行的代码,包括CPU和GPU。
下面是一个使用ROCm的HIP API实现的简单向量加法程序示例。这个程序将创建两个向量,将它们相加,并输出结果。

#include <hip/hip_runtime.h>
#include <iostream>

__global__ void vectorAdd(const float *A, const float *B, float *C, int N) {
    int i = hipBlockIdx.x * hipBlockDim.x + hipThreadIdx.x;
    if (i < N) {
        C[i] = A[i] + B[i];
    }
}

int main() {
    int N = 1 << 10; // 向量大小
    size_t size = N * sizeof(float);

    float *h_A, *h_B, *h_C;
    float *d_A, *d_B, *d_C;

    // 分配主机内存
    h_A = new float[N];
    h_B = new float[N];
    h_C = new float[N];

    // 初始化主机向量
    for (int i = 0; i < N; i++) {
        h_A[i] = i;
        h_B[i] = i * 2;
    }

    // 分配设备内存
    hipMalloc((void **)&d_A, size);
    hipMalloc((void **)&d_B, size);
    hipMalloc((void **)&d_C, size);

    // 将主机向量复制到设备
    hipMemcpy(d_A, h_A, size, hipMemcpyHostToDevice);
    hipMemcpy(d_B, h_B, size, hipMemcpyHostToDevice);

    // 启动核函数
    hipLaunchKernelGGL(vectorAdd, dim3((N + 255) / 256), dim3(256), 0, 0, d_A, d_B, d_C, N);

    // 将结果从设备复制回主机
    hipMemcpy(h_C, d_C, size, hipMemcpyDeviceToHost);

    // 验证结果
    for (int i = 0; i < N; i++) {
        if (h_C[i] != (h_A[i] + h_B[i])) {
            std::cout << "Error: C[" << i << "] != A[" << i << "] + B[" << i << "]" << std::endl;
            break;
        }
    }

    // 释放设备内存
    hipFree(d_A);
    hipFree(d_B);
    hipFree(d_C);

    // 释放主机内存
    delete[] h_A;
    delete[] h_B;
    delete[] h_C;

    return 0;
}

在这个程序中,我们首先定义了一个名为`vectorAdd`的核函数,它将在GPU上执行。然后在`main`函数中,我们分配了主机和设备的内存,初始化了两个向量,并将它们复制到设备内存中。
接下来,我们调用`hipLaunchKernelGGL`函数来启动核函数。核函数执行后,我们将结果从设备内存复制回主机内存,并验证结果是否正确。
最后,我们释放了所有分配的内存资源。

要编译和运行这个程序,你需要安装ROCm软件平台,并使用`hipcc`编译器。例如,你可以使用以下命令来编译这个程序:

hipcc -o vector_add vector_add.cu
./vector_add

请注意,这个程序是一个基本的示例,实际使用时可能需要根据具体情况进行调整。此外,为了提高性能,你可能需要调整线程块大小和网格大小等参数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1584736.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

BPMN.JS中文教程学习

基础篇 vue bpmn.js 建模BpmnModeler将数据转图形bpmnModeler.importXML // basic.vue<script>// 引入相关的依赖import BpmnModeler from bpmn-js/lib/Modelerimport {xmlStr} from ../mock/xmlStr // 这里是直接引用了xml字符串export default {name: ,components: {…

使用 Docker 部署 Open-Resume 在线简历平台

1&#xff09;Open-Resume 介绍 GitHub&#xff1a; https://github.com/xitanggg/open-resume Open-Resume 是一款功能强大的开源 简历生成器 和 简历解析器 。可以帮助我们快速的生成个人简历&#xff0c;并定制化不同的主题和布局风格。该项目的目标是为每个人提供免费的现…

Qt5 编译 Qt Creator 源码中的 linguist 模块

文章目录 下载 Qt Creator 源码手动翻译多语言自动翻译多语言 下载 Qt Creator 源码 Github: https://github.com/qt/qttools 笔记打算用 Qt 5.12.12 来编译 qt creator-linguist 所以笔者下载的是 tag - 5.12.12 &#xff0c;解压后如下&#xff0c;先删除多余的文件&#xf…

视觉SLAM学习打卡【10】-后端·滑动窗口法位姿图

本节是对上一节BA的进一步简化&#xff0c;旨在提高优化实时性.难点在于位姿图部分的雅可比矩阵求解&#xff08;涉及李代数扰动模型求导&#xff09;&#xff0c;书中的相关推导存在跳步&#xff08;可能数学功底强的人认为过渡的理所当然&#xff09;&#xff0c;笔者参考了知…

B站广告推广操作教程及费用?

哔哩哔哩&#xff08;B站&#xff09;作为国内极具影响力的年轻人文化社区&#xff0c;已成为众多品牌与企业触达目标受众、提升品牌影响力的重要阵地。然而&#xff0c;面对B站复杂的广告系统与精细化运营需求&#xff0c;许多广告主可能对如何高效开展B站广告推广感到困惑。云…

2024年同城网总流量全新生态,个人工作室落地式游戏玩法,单账户月入3万

我要为大家解读的是本地生活新项目&#xff0c;这个业务模式中&#xff0c;即使是低收入的玩法&#xff0c;一个月赚取万儿八千也是完全可行的。而高收入的玩法&#xff0c;一单的收入甚至能超过一万。目前&#xff0c;你的圈子里已经有一些同行业的人开始以个人工作室的形式去…

stm32开发之threadx+netxduo(结合 modbus 编写tcp接口程序)

前言 本篇结合freemodbus源码程序进行移植,驱动实现的接口为modbus tcp需要知道threadx的 事件标志组、信号量、线程相关的知识需要知道netxduo tcp方面的api和创建流程方面的知识 freemodbus程序源码 本次使用的源码来自于rt-thread软件包里面的&#xff0c;可以参考之前的…

linux查看网络连接数

目录 netstat top netstat 1.netstat查看当前主机上网络连接信息&#xff0c;端口号&#xff0c;pid,程序名等等 #直接查看 netstat -anp #一般使用的时候&#xff0c;可能要筛选 #比如8080端口是否被占用 netstat -anp | grep 8080 #minio服务占用了那些端口 netstat -anp …

掌握判断IPv4地址是否正确的方法

在数字通信和互联网领域中&#xff0c;IPv4地址作为标识网络设备的核心元素&#xff0c;其正确性至关重要。一个有效的IPv4地址能够确保设备在网络中的正常通信和交互&#xff0c;而错误的IPv4地址则可能导致连接失败、通信中断甚至网络安全问题。因此&#xff0c;掌握判断IPv4…

【docker】之linux写shell脚本备份线上数据库(备份为dump文件)

目录 1. SH文件1.1 SH文件示例1.2 文件解释1.3 .sh文件执行 2. 备份线上数据库的.sh文件2.1 文件命令解析 3. 命令执行4. 线下dump文件的恢复与备份 环境&#xff1a;linux容器&#xff1a;docker 1. SH文件 SH文件通常指的是 Shell 脚本文件&#xff0c;文件后缀名为.sh&…

Spring Boot统一功能处理(一)

本篇主要介绍Spring Boot的统一功能处理中的拦截器。 目录 一、拦截器的基本使用 二、拦截器实操 三、浅尝源码 初始化DispatcherServerlet 处理请求&#xff08;doDispatch) 四、适配器模式 一、拦截器的基本使用 在一般的学校或者社区门口&#xff0c;通常会安排几个…

【C++学习】C++11新特性(第一节)

文章目录 ♫一.文章前言♫二.C11新特性♫一.统一的列表初始化♫二.std::initializer_list♫三.声明♫四.decltype关键字♫五.nullptr♫六.新增加容器---静态数组array、forward_list以及unordered系列♫6.1unordered_map与unoredered_set♫6.2array♫6.3 forward_list&#xff…

Leetcode算法训练日记 | day18

一、找树左下角的值 1.题目 Leetcode&#xff1a;第 513 题 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: 输入: root [2,1,3] 输出: 1示例 2: 输入: [1,2,3,4,null,5,6,null,null,7] 输出:…

nandgame中的Memory(内存操作):栈、堆、静态区

Push Memory Push Memory 将内存中的值push到栈内堆栈顶部的值是一个内存地址。从堆栈中弹出地址。获取内存地址的当前内容&#xff0c;并将其推送到堆栈上。POP_A //堆栈顶部的值是一个内存地址。从堆栈中弹出地址。 D *A //获取内存地址的当前内容 PUSH_D //将其推送到…

JVM性能调优——运行时参数

文章目录 1、JVM参数选项类型1.1、标准参数选项1.2、非标准参数选项1.3、非稳定参数选项 2、添加JVM参数的方式3、常用JVM参数选项4、通过Java代码获取JVM参数5、小结 熟悉JVM参数对于系统调优是非常重要的。比如一个高流量的延迟的电子交易平台&#xff0c;它要求的响应时间都…

ROS机器人未知环境自主探索功能包explore_lite最全源码详细解析(五)

本系列文章主要针对ROS机器人常使用的未知环境自主探索功能包explore_lite展开全源码的详细解析&#xff0c;并进行概括总结。 本系列文章共包含六篇文章&#xff0c;前五篇文章主要介绍explore_lite功能包中 explore.cpp、costmap_tools.h、frontier_search.cpp、costmap_clie…

MySQL:关于数据库的一些练习题

文章目录 前面的内容已经把数据库的一些必要知识已经储备好了&#xff0c;因此下面就对于这些语句进行一些练习&#xff1a; 批量插入数据 insert into actor values (1, PENELOPE, GUINESS, 2006-02-15 12:34:33), (2, NICK, WAHLBERG, 2006-02-15 12:34:33);SQL202 找出所有…

C/S医学检验LIS实验室信息管理系统源码 医院LIS源码

LIS系统即实验室信息管理系统。LIS系统能实现临床检验信息化&#xff0c;检验科信息管理自动化。其主要功能是将检验科的实验仪器传出的检验数据经数据分析后&#xff0c;自动生成打印报告&#xff0c;通过网络存储在数据库中&#xff0c;使医生能够通过医生工作站方便、及时地…

一起学习python——基础篇(14)

今天讲一下python的json解析方式。 上一篇文章讲述了将传参数据转换为json格式的数据传给后台&#xff0c;如果后端返回的json格式数据&#xff0c;我们该如何解析呢&#xff1f; 例子一&#xff1a;简单的json数据格式 如果后端返回的json数据如下&#xff0c; { "na…

【leetcode面试经典150题】34.有效的数独(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…