摩尔线程 国产显卡 MUSA 并行编程 学习笔记-2024/12/03

 Learning Roadmap:

Section 1: Intro to Parallel Programming & MUSA

  1. Deep Learning Ecosystem(摩尔线程 国产显卡 MUSA 并行编程 学习笔记-2024/11/30-CSDN博客)
  2. Ubuntu+Driver+Toolkit+conda+pytorch+torch_musa环境安装(2024/11/24-Ubuntu Windows双系统安装 | 2024/11/30-GPU驱动&MUSA Toolkit安装)
  3. C/C++ Review(摩尔线程国产显卡 MUSA 并行编程学习笔记-2024/11/22-CSDN博客)
  4. GPU intros(摩尔线程国产显卡 MUSA 并行编程学习笔记-2024/11/25-CSDN博客)
  5. GPU硬件架构 (摩尔线程国产显卡 MUSA 并行编程学习笔记-2024/11/26-CSDN博客)
  6. Write First Kernels (Here) (2024/11/27-线程层级 | 2024/11/28-First MUSA Kernel to Count Thread | 2024/12/02-向量相加)
  7. MUSA API
  8. Faster Matrix Multiplication
  9. Triton
  10. Pytorch Extensions(摩尔线程国产显卡 MUSA 并行编程学习笔记-2024/11/21-CSDN博客)
  11. MNIST Multilayer Perceptron

Section 2: Parallel Programming & MUSA in Depth

  1. Analyzing Parallel Program Performance on a Quad-Core CPU
  2. Scheduling Task Graphs on a Multi-Core CPU
  3. A Simple Renderer in MUSA
  4. Optimizing DNN Performance on DNN Accelerator Hardware
  5. llm.c

Ref:摩尔学院 High-Performance Computing with GPUs | Stanford CS149 - Video | Stanford CS149 - Syllabus

Kernel to Add Vector (3D)

Ref:  High-Performance Computing with GPUs Chapter 5

下面的代码将用CPU与GPU分别对两个长度为1000万的向量进行相加,并计算对应的平均耗时,其中GPU相加分别采用了两种Kernel,其中一个Kernel定义了三维的Block和Grid,另一个Kernel则使用了一维的Block和Grid

代码地址

MUSA PLAY GROUND - Github

代码

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <musa_runtime.h>
#include <math.h>
#include <iostream>#define N 10000000  // Vector size = 10 million
#define BLOCK_SIZE_1D 1024
#define BLOCK_SIZE_3D_X 16
#define BLOCK_SIZE_3D_Y 8
#define BLOCK_SIZE_3D_Z 8
// 16 * 16 * 8 = 2048// CPU vector addition
void vector_add_cpu(float *a, float *b, float *c, int n) {for (int i = 0; i < n; i++) {c[i] = a[i] + b[i];}
}// MUSA kernel for 1D vector addition
__global__ void vector_add_gpu_1d(float *a, float *b, float *c, int n) {int i = blockIdx.x * blockDim.x + threadIdx.x;// one add, one multiply, one storeif (i < n) {c[i] = a[i] + b[i];// one add, one store}
}// MUSA kernel for 3D vector addition
__global__ void vector_add_gpu_3d(float *a, float *b, float *c, int nx, int ny, int nz) {int i = blockIdx.x * blockDim.x + threadIdx.x;int j = blockIdx.y * blockDim.y + threadIdx.y;int k = blockIdx.z * blockDim.z + threadIdx.z;// 3 adds, 3 multiplies, 3 storesif (i < nx && j < ny && k < nz) {int idx = i + j * nx + k * nx * ny;if (idx < nx * ny * nz) {c[idx] = a[idx] + b[idx];}}// you get the point...
}// Initialize vector with random values
void init_vector(float *vec, int n) {for (int i = 0; i < n; i++) {vec[i] = (float)rand() / RAND_MAX;}
}// Function to measure execution time
double get_time() {struct timespec ts;clock_gettime(CLOCK_MONOTONIC, &ts);return ts.tv_sec + ts.tv_nsec * 1e-9;
}
int main() {float *h_a, *h_b, *h_c_cpu, *h_c_gpu_1d, *h_c_gpu_3d;float *d_a, *d_b, *d_c_1d, *d_c_3d;size_t size = N * sizeof(float);// Allocate host memoryh_a = (float*)malloc(size);h_b = (float*)malloc(size);h_c_cpu = (float*)malloc(size);h_c_gpu_1d = (float*)malloc(size);h_c_gpu_3d = (float*)malloc(size);// Initialize vectorssrand(time(NULL));init_vector(h_a, N);init_vector(h_b, N);// Allocate device memorymusaMalloc(&d_a, size);musaMalloc(&d_b, size);musaMalloc(&d_c_1d, size);musaMalloc(&d_c_3d, size);// Copy data to devicemusaMemcpy(d_a, h_a, size, musaMemcpyHostToDevice);musaMemcpy(d_b, h_b, size, musaMemcpyHostToDevice);// Define grid and block dimensions for 1Dint num_blocks_1d = (N + BLOCK_SIZE_1D - 1) / BLOCK_SIZE_1D;// Define grid and block dimensions for 3Dint nx = 100, ny = 100, nz = 1000; // N = 10000000 = 100 * 100 * 1000dim3 block_size_3d(BLOCK_SIZE_3D_X, BLOCK_SIZE_3D_Y, BLOCK_SIZE_3D_Z);dim3 num_blocks_3d((nx + block_size_3d.x - 1) / block_size_3d.x,(ny + block_size_3d.y - 1) / block_size_3d.y,(nz + block_size_3d.z - 1) / block_size_3d.z);// Warm-up runsprintf("Performing warm-up runs...\n");for (int i = 0; i < 3; i++) {vector_add_cpu(h_a, h_b, h_c_cpu, N);vector_add_gpu_1d<<<num_blocks_1d, BLOCK_SIZE_1D>>>(d_a, d_b, d_c_1d, N);vector_add_gpu_3d<<<num_blocks_3d, block_size_3d>>>(d_a, d_b, d_c_3d, nx, ny, nz);musaDeviceSynchronize();}// Benchmark CPU implementationprintf("Benchmarking CPU implementation...\n");double cpu_total_time = 0.0;for (int i = 0; i < 5; i++) {double start_time = get_time();vector_add_cpu(h_a, h_b, h_c_cpu, N);double end_time = get_time();cpu_total_time += end_time - start_time;}double cpu_avg_time = cpu_total_time / 5.0;// Benchmark GPU 1D implementationprintf("Benchmarking GPU 1D implementation...\n");double gpu_1d_total_time = 0.0;for (int i = 0; i < 100; i++) {musaMemset(d_c_1d, 0, size);  // Clear previous resultsdouble start_time = get_time();vector_add_gpu_1d<<<num_blocks_1d, BLOCK_SIZE_1D>>>(d_a, d_b, d_c_1d, N);musaDeviceSynchronize();double end_time = get_time();gpu_1d_total_time += end_time - start_time;}double gpu_1d_avg_time = gpu_1d_total_time / 100.0;// Verify 1D results immediatelymusaMemcpy(h_c_gpu_1d, d_c_1d, size, musaMemcpyDeviceToHost);bool correct_1d = true;for (int i = 0; i < N; i++) {if (fabs(h_c_cpu[i] - h_c_gpu_1d[i]) > 1e-4) {correct_1d = false;std::cout << i << " cpu: " << h_c_cpu[i] << " != " << h_c_gpu_1d[i] << std::endl;break;}}printf("1D Results are %s\n", correct_1d ? "correct" : "incorrect");// Benchmark GPU 3D implementationprintf("Benchmarking GPU 3D implementation...\n");double gpu_3d_total_time = 0.0;for (int i = 0; i < 100; i++) {musaMemset(d_c_3d, 0, size);  // Clear previous resultsdouble start_time = get_time();vector_add_gpu_3d<<<num_blocks_3d, block_size_3d>>>(d_a, d_b, d_c_3d, nx, ny, nz);musaDeviceSynchronize();double end_time = get_time();gpu_3d_total_time += end_time - start_time;}double gpu_3d_avg_time = gpu_3d_total_time / 100.0;// Verify 3D results immediatelymusaMemcpy(h_c_gpu_3d, d_c_3d, size, musaMemcpyDeviceToHost);bool correct_3d = true;for (int i = 0; i < N; i++) {if (fabs(h_c_cpu[i] - h_c_gpu_3d[i]) > 1e-4) {correct_3d = false;std::cout << i << " cpu: " << h_c_cpu[i] << " != " << h_c_gpu_3d[i] << std::endl;break;}}printf("3D Results are %s\n", correct_3d ? "correct" : "incorrect");// Print resultsprintf("CPU average time: %f milliseconds\n", cpu_avg_time * 1000);printf("GPU 1D average time: %f milliseconds\n", gpu_1d_avg_time * 1000);printf("GPU 3D average time: %f milliseconds\n", gpu_3d_avg_time * 1000);printf("Speedup (CPU vs GPU 1D): %fx\n", cpu_avg_time / gpu_1d_avg_time);printf("Speedup (CPU vs GPU 3D): %fx\n", cpu_avg_time / gpu_3d_avg_time);printf("Speedup (GPU 1D vs GPU 3D): %fx\n", gpu_1d_avg_time / gpu_3d_avg_time);// Free memoryfree(h_a);free(h_b);free(h_c_cpu);free(h_c_gpu_1d);free(h_c_gpu_3d);musaFree(d_a);musaFree(d_b);musaFree(d_c_1d);musaFree(d_c_3d);return 0;
}

编译

    mcc 01_vector_add_v2.mu -o vector_add_v2 -mtgpu -O2 -lmusart./vector_add_v2

输出结果

如图所示,结果输出了CPU与GPU 对于长度为1000万的两个向量的相加,20次的平均速度,并验证了结果的准确性,可以看到通过定义3D block & grid的GPU Kernel不如定义了1D block & grid的 GPU Kernel的速度

Notes

如无必要,定义1D Block就可以

  1. 这里可以看到相比定义三维Grid & Block Kernel所需要的3次add, 3次multiplies,3次stores,通过1D Gird & Block 的Kernel只需要1次Add, mutiply 和Store,并且整个代码逻辑上要清晰很多,如果Kernel不是一定要计算三维强相关的任务时,定义1D block & grid在计算与简洁性上均有优势
// MUSA kernel for 1D vector addition
__global__ void vector_add_gpu_1d(float *a, float *b, float *c, int n) {int i = blockIdx.x * blockDim.x + threadIdx.x;// one add, one multiply, one storeif (i < n) {c[i] = a[i] + b[i];// one add, one store}
}// MUSA kernel for 3D vector addition
__global__ void vector_add_gpu_3d(float *a, float *b, float *c, int nx, int ny, int nz) {int i = blockIdx.x * blockDim.x + threadIdx.x;int j = blockIdx.y * blockDim.y + threadIdx.y;int k = blockIdx.z * blockDim.z + threadIdx.z;// 3 adds, 3 multiplies, 3 storesif (i < nx && j < ny && k < nz) {int idx = i + j * nx + k * nx * ny;if (idx < nx * ny * nz) {c[idx] = a[idx] + b[idx];}}// you get the point...
}

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

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

相关文章

基于 MindQuantum 实现对 “天衍” 量子云平台真机的比特映射

MindQuantum 目前只支持量子模拟器&#xff0c;如果需要获得量子算法在真机上的实测数据&#xff0c;可以借助“天衍”量子云平台提供的真机。本文将介绍如何基于 MindQuantum 绘制“天衍”真机的拓扑图&#xff0c;并进而实现比特映射。 关于 MindQuantum 涉及比特映射的教程…

2025客服知识库工具推荐哪些?

在2025年&#xff0c;企业对于客服知识库工具的需求日益增长&#xff0c;这些工具不仅能够提升客户服务的效率和质量&#xff0c;还能增强客户满意度和忠诚度。以下是几款备受推崇的客服知识库工具。 1. HelpLook AI知识库 HelpLook AI知识库是一款企业级AI知识库系统&#x…

Docker运行hello-world镜像出现错误

错误类型&#xff1a; 解决方案&#xff1b; 配置加速地址&#xff1a;设置registry mirror sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-EOF {"registry-mirrors": ["https://do.nark.eu.org","https://dc.j8.work"…

西南大学软件工程考研录取情况分析

西南大学软件工程学硕近三年呈现出招生规模稳定、复试线稳中有升的特点。2024届实际录取8人&#xff0c;复试分数线305分&#xff0c;复试录取率67%&#xff0c;相比去年复试线略有下降但仍高于2022届&#xff0c;显示出温和的竞争态势。 详细分析 1. 统招录取人数分析 2022-…

【测试工具JMeter篇】JMeter性能测试入门级教程(八):JMeter参数关联

JMeter参数关联&#xff0c;就是请求或者线程之间通过传递参数建立联系。一般&#xff0c;我们将一个请求的响应参数&#xff0c;作为另一个请求的入参。比如登录后的操作&#xff0c;第一步用来实现登录操作&#xff0c;然后将请求返回的token提取出来保存到某一个变量当中&am…

运算符重载(五)

目录 const成员函数const对象不可以调用非const成员函数非const对象可以调用const成员函数const成员函数内不可以调用其它的非const成员函数非const成员函数内可以调用其它的const成员函 取地址及const取地址操作符重载const补充场景1场景2场景3场景4 const成员函数 将const修…

论文阅读笔记:Adaptive Rotated Convolution for Rotated Object Detection

论文阅读笔记&#xff1a;Adaptive Rotated Convolution for Rotated Object Detection 1 背景1.1 问题1.2 提出的方法 2 创新点3 方法4 模块4.1 旋转卷积核4.2 路由函数4.3 自适应旋转卷积模块 5 效果5.1 与SOTA方法对比5.2 消融实验 论文&#xff1a;https://arxiv.org/pdf/2…

OPenCV 图片局部放大

m_image cv::imread("C:/Code/JPG/1.jpg");if (m_image.empty()) return;cv::imshow("原始图像", m_image); // TODO: 在此添加控件通知处理程序代码int width m_image.cols;int height m_image.rows;// 确定要放大的区域&#xff08;这里是图像中心部分…

SpringBoot项目启动报错-Slf4j日志相关类找不到

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

剧本杀门店预约系统开发,助力门店业务升级

剧本杀门店系统是一个统一管理门店的应用程序&#xff0c;能够让消费者通过系统与好友组局预订剧本杀游戏&#xff0c;节省到线下门店排队预约的时间&#xff0c;提高玩家的游戏体验感。同时商家也可以借助小程序高效管理、运营门店&#xff0c;提高门店的整体服务质量。 小程…

c语言指针练习

1.已知数组a[10]和b[10]中元素的值递增有序&#xff0c;用指针实现将两个数组中的元素按递增的顺序输出。 #include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc, const char *argv[]) {int a[10]{1,3,5,7,9,11,13,15,17,19};int…

MYSQL中的增删改查操作(如果想知道MYSQL中有关增删改查操作的知识,那么只看这一篇就足够了!)

前言&#xff1a;在 MySQL 中&#xff0c;增、删、改、查&#xff08;CRUD&#xff09;操作是基本的数据库操作&#xff0c;增操作&#xff08;INSERT&#xff09;用于插入数据&#xff0c;删操作&#xff08;DELETE&#xff09;用于删除数据&#xff0c;改操作&#xff08;UPD…

代码随想录-算法训练营day36(贪心算法06:单调递增的数字,监控二叉树,总结)

第八章 贪心算法 part06● 738.单调递增的数字 ● 968.监控二叉树 ● 总结 详细布置 738.单调递增的数字 https://programmercarl.com/0738.%E5%8D%95%E8%B0%83%E9%80%92%E5%A2%9E%E7%9A%84%E6%95%B0%E5%AD%97.html 968.监控二叉树 &#xff08;可以跳过&#xff09;本题是…

NeurIPS Spotlight|从分类到生成:无训练的可控扩散生成

近年来&#xff0c;扩散模型&#xff08;Diffusion Models&#xff09;已成为生成模型领域的研究前沿&#xff0c;它们在图像生成、视频生成、分子设计、音频生成等众多领域展现出强大的能力。然而&#xff0c;生成符合特定条件&#xff08;如标签、属性或能量分布&#xff09;…

Neo4j:图数据库使用入门

文章目录 一、Neo4j安装1、windows安装&#xff08;1&#xff09;准备环境&#xff08;2&#xff09;下载&#xff08;3&#xff09;解压&#xff08;4&#xff09;运行&#xff08;5&#xff09;基本使用 2、docker安装 二、CQL语句1、CQL简介2、CREATE 命令&#xff0c;创建节…

声音克隆GPT-SoVITS

作者&#xff1a;吴业亮 博客&#xff1a;wuyeliang.blog.csdn.net 一、原理介绍 GPT-SoVITS&#xff0c;作为一款结合了GPT&#xff08;生成预训练模型&#xff09;和SoVITS&#xff08;基于变分信息瓶颈技术的歌声转换&#xff09;的创新工具&#xff0c;正在声音克隆领域掀…

嵌入式Linux,标准I/O探究,函数相关详解。

标准 I/O 虽然是对文 件 I/O 进行了封装&#xff0c;但事实上并不仅仅只是如此&#xff0c;标准 I/O 会处理很多细节&#xff0c;譬如分配 stdio 缓冲区、以优化的块长度执行 I/O 等。 1.标准 I/O 库介绍 通常标准 I/O 库函数相关的函数定义都在头文件 <stdio.h&g…

github使用SSH进行克隆仓库

SSH 密钥拉取git 查询密钥是否存在 s -al ~/.ssh这个文件夹下 known_hosts 就是存在的密钥文件 创建密钥文件 ssh-keygen -t rsa -b 4096 -C "testtt.com"-t rsa 是 rsa 算法加密 -b 是指定密钥的长度&#xff08;以位为单位&#xff09;。 -C 是用于给密钥添加注…

江铃集团新能源携四款车型亮相香港车展,国际化布局成果显著

12月5日&#xff0c;2024年香港国际汽车博览会&#xff08;香港车展&#xff09;盛大开幕&#xff0c;来自全球上百个品牌齐聚一堂&#xff0c;上演了一场汽车盛筵。江铃集团新能源作为自主品牌的代表车企之一&#xff0c;持续推进国际化布局&#xff0c;为了满足不同地区用户的…

使用Unity脚本模拟绳索、布料(碰撞)

效果演示&#xff1a; 脚本如下&#xff1a; using System.Collections; using System.Collections.Generic; using UnityEngine;namespace PhysicsLab {public class RopeSolver : MonoBehaviour {public Transform ParticlePrefab;public int Count 3;public int Space 1;…