首页 > 其他分享 >Hello Cuda(二)——向量加法

Hello Cuda(二)——向量加法

时间:2023-08-24 17:13:44浏览次数:29  
标签:time int void FLOAT Cuda 加法 NULL Hello nbytes

#include <stdio.h>
#include <stdlib.h>
#include <cuda.h>
#include <math.h>
#include <cuda_runtime.h>
#include <device_launch_parameters.h>

typedef float FLOAT;

double get_time();
void warm_up();
void vec_add_host(FLOAT* x, FLOAT* y, FLOAT* z, int N); // CPU端
__global__ void vec_add_device(FLOAT* x, FLOAT* y, FLOAT* z, int N);  // GPU端

// 二维GRID+1维BLOCK
#define get_tid() ((blockIdx.y * gridDim.x + blockIdx.x) * blockDim.x + threadIdx.x)
#define get_bid() (blockIdx.y * gridDim.x + blockIdx.x)

#define WINDOWS 0

#if WINDOWS
#include <windows.h>
double get_time()
{
    LARGE_INTEGER timer;
    static LARGE_INTEGER fre;
    static int init = 0;
    double t;

    if(init != 1)
    {
        QueryPerformanceFrequency(&fre);
        init = 1;
    }

    QueryPerformanceFrequency(&timer);
    t = timer.QuadPart * 1. / fre.QuadPart;
    return t;

}

#else

#include <sys/time.h>
#include <time.h>

double get_time()
{
    struct timeval tv;
    double t;
    gettimeofday(&tv, (struct timezone*)0);
    t = tv.tv_sec + (double)tv.tv_usec*1e-6;
    return t;
    
}

#endif


// GPU WARM-UP
__global__ void warmup_knl(void)
{
    int i, j;
    i = 1;
    j = 1;
    i = i + j;
}

// CPU WARM-UP
void warm_up()
{
    int i = 0;
    for (; i < 0; ++i)
    {
        warmup_knl <<<1, 256>>> ();
    }
}

// CPU端-HOST
void vec_add_host(FLOAT* x, FLOAT* y, FLOAT* z, int N)
{
    int i;
    for (int i = 0; i < N; ++i)
        z[i] = x[i] + y[i] + z[i];
}

__global__ void vec_add_device(FLOAT* x, FLOAT* y, FLOAT* z, int N)
{
    int idx = get_tid();
    if (idx < N)
        z[idx] = x[idx] + y[idx] + z[idx];
}

int main()
{
    int N = 20000000;
    int nbytes = N * sizeof(FLOAT);

    // 二维GRID 一维BLOCK
    int bs = 256; // BLOCK NUMBER
    int s = ceil(sqrt((N + bs - 1.) / bs));  // GRID SIZE 
    dim3 grid = dim3(s, s);

    FLOAT* dx = NULL, *hx = NULL;
    FLOAT* dy = NULL, *hy = NULL;
    FLOAT* dz = NULL, *hz = NULL;

    int iter = 30;
    int i;
    double th, td;

    warm_up();

    // 分配GPU内存
    cudaMalloc((void**)&dx, nbytes);
    cudaMalloc((void**)&dy, nbytes);
    cudaMalloc((void**)&dz, nbytes);

    if(dx == NULL || dy == NULL || dz == NULL)
    {
        printf("Couldn't allocate GPU Memory");
        return -1;
    }

    // 分配CPU内存
    hx = (FLOAT*)malloc(nbytes);
    hy = (FLOAT*)malloc(nbytes);
    hz = (FLOAT*)malloc(nbytes);

    if(hx == NULL || hy == NULL || hz == NULL)
    {
        printf("Couldn't allocate CPU Memory");
    }

    // 初始化
    for(int i = 0; i < N; ++i)
    {
        hx[i] = 1;
        hy[i] = 1;
        hz[i] = 1;
    }

    // 拷贝数据从主机CPU至设备GPU
    cudaMemcpy(dx, hx, nbytes, cudaMemcpyHostToDevice); 
    cudaMemcpy(dy, hy, nbytes, cudaMemcpyHostToDevice);
    cudaMemcpy(dz, hz, nbytes, cudaMemcpyHostToDevice);

    warm_up();

    cudaThreadSynchronize(); // 异步线程开启
     // 调用GPU
    td = get_time();
    for(i = 0; i < iter; ++i)
        vec_add_device<<<grid, bs>>> (dx, dy, dz, N);
    td = get_time() - td;
    // 严格上这里需要有一个从设备端拷贝数据到主机端的过程
    // cudaMemcpy(hx, dx, nbytes, cudaMemcpyDevicetoHost);
    
    // 调用CPU
    th = get_time();
    for(i = 0; i < iter; ++i)
        vec_add_host(hx, hy, hz, N);
    th = get_time() - th;

    printf("GPU time: %.4f, CPU time: %.4f. SppedUp: %g \n", td, th, th/td);

    // 释放资源
    free(hx);
    free(hy);
    free(hz);
    cudaFree(hx);
    cudaFree(hy);
    cudaFree(hz);
    

    return 0;
}
GPU time: 0.0109, CPU time: 2.6454. SppedUp: 242.811 

标签:time,int,void,FLOAT,Cuda,加法,NULL,Hello,nbytes
From: https://www.cnblogs.com/XL2COWARD/p/MyCuda_2.html

相关文章

  • Hello Cuda(一)——GPU设备检测
    #include"device_launch_parameters.h"#include<iostream>intmain(intargc,char*argv[]){intdeviceCount;//设备数目cudaGetDeviceCount(&deviceCount);for(inti=0;i<deviceCount;i++){cudaDeviceProp......
  • 1001:Hello,World!
    1001:Hello,World!时间限制:1000ms      内存限制:65536KB提交数:345055   通过数:168663【题目描述】编写一个能够输出“Hello,World!”的程序,这个程序常常作为一个初学者接触一门新的编程语言所写的第一个程序,也经常用来测试开发、编译环境是否能够正常......
  • CUDA -编辑模型
    编程模型可以理解为,我们要用到的语法,内存结构,线程结构等这些我们写程序时我们自己控制的部分,这些部分控制了异构计算设备的工作模式,都是属于编程模型。GPU中大致可以分为:核函数内存管理线程管理流从宏观上我们可以从以下几个环节完成CUDA应用开发:领域层逻辑层硬件层第......
  • 期货交易做的不是加法,而是减法!
    投机市场本身是中性的市场,它不好,但是也不坏。所以它不是幸运者的天堂,也不应该是失意者的地狱。它只是一个有自己运行规律的市场。它只是忠实的执行着所有交易者提出的交易需求,它从不会取悦某一个交易者,也不会去刻意讨好某一个交易者不管你是做多还是做空,它总是有自己的方向,所有的好......
  • Ubuntu16.04+CUDA8.0+OpenCV3.1+python+caffe+faster-rcnn环境配置
    前言Ubuntu1604注意事项CUDA80安装显卡驱动安装CUDA80编译CUDASampleOpenCV31pythonCaffe安装CaffeMNIST数据集测试faster-rcnn后记前言经过大概两个星期的配置,终于将faster-rcnn安装好了,期间重装了大概十次系统,查阅了无数多文献博客,遇到了无数多坑。本人写这篇文章就是希望读者......
  • Hello, SpringMVC
    springMVC的执行流程 具体流程(1)当用户通过浏览器发起一个HTTP请求,请求直接到前端控制器DispatcherServlet;(2)前端控制器接收到请求以后调用处理器映射器HandlerMapping,处理器映射器根据请求的URL找到具体的Handler,并将它返回给前端控制器;(3)前端控制器调用处理器适配器Handle......
  • 4.Acwing基础课第791题-简单-高精度加法
    4.Acwing基础课第791题-简单-高精度加法题目描述给定两个正整数(不含前导0),计算它们的和。输入格式共两行,每行包含一个整数。输出格式共一行,包含所求的和。数据范围1≤整数长度≤100000输入样例1223输入样例35思路解析:算法:时间复杂度:*O(nlog(n))*解题思路:代码:......
  • R语言lasso惩罚稀疏加法(相加)模型SPAM拟合非线性数据和可视化
    全文链接:https://tecdat.cn/?p=33462原文出处:拓端数据部落公众号本文将关注R语言中的LASSO(LeastAbsoluteShrinkageandSelectionOperator)惩罚稀疏加法模型(SparseAdditiveModel,简称SPAM)。SPAM是一种用于拟合非线性数据的强大工具,它可以通过估计非线性函数的加法组件来捕捉......
  • GPU与CUDA C编程基本知识
    一、CPU与GPU的异同CPU:延迟导向内核,所谓延迟,指指令发出到得到结果中间经历的时间。GPU:吞吐导向内核,所谓吞吐量指单位时间内处理的指令数量。其适合于计算密集或者数据并行的场合。二、CUDA2.1简介CUDA(ComputeUnifiedDeviceArchitecture)是由英伟达公司2007年开始推出,初衷......
  • WSL2 Ubuntu20.04 配置 CUDA
    前言本文主要讲解如何在Widnows11环境下的WSL2(Ubuntu20.04)配置CUDA来启用GPU加速(本文默认您已经在Windows上安装完成NvidiaCUDA)配置流程检查驱动打开GeForceExperience检查驱动程序的情况,需要更新到最新版,最后重启GeForceExperience。安装CUDA命令生成生......