CUDA入门(六) 异步并行执行解析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 为了更好地压榨GPU和CPU,很多时候都使用异步并行的方法让主机端与设备端并行执行,即控制在设备没有完成任务请求前就被返回给主机端。 异步执行的意义在于:首先,处于同一数据流内的计算与数据拷贝都是依次进行的,但一个流内的计算可以和另一个流的数据传输同时进行,因此通过异步执行就能够使GPU中的执行单元与存储器单元同时工作,更好地压榨GPU的性能;其次,当GPU在进行计算或者数

为了更好地压榨GPU和CPU,很多时候都使用异步并行的方法让主机端与设备端并行执行,即控制在设备没有完成任务请求前就被返回给主机端。
异步执行的意义在于:首先,处于同一数据流内的计算与数据拷贝都是依次进行的,但一个流内的计算可以和另一个流的数据传输同时进行,因此通过异步执行就能够使GPU中的执行单元与存储器单元同时工作,更好地压榨GPU的性能;其次,当GPU在进行计算或者数据传输时就返回给主机线程,主机不必等待GPU运行完毕就可以进行进行一些计算,更好地压榨了CPU的性能。
之前,单单使用GPU的同步函数,会使设备在完成请求任务前,不会返回主机线程,主机线程将进入让步(yield)、阻滞(block)或者自旋(spin)。
下面一个SDK简单的异步并行执行的程序:


#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <memory.h>
#include<time.h>
#include"helper_timer.h"


__global__ void increment_kernel(int *g_data, int inc_value)
{
    int idx = blockIdx.x*blockDim.x + threadIdx.x;
    g_data[idx] = g_data[idx] + inc_value;


}

int correct_output(int *data, const int n, const int x)
{
    for (int i = 0; i < n; i++)
        if (data[i] != x)
            return 0;
}
int main(int argc, char *argv[])
{
    cudaDeviceProp deviceProps;
    cudaGetDeviceProperties(&deviceProps, 0);
    printf("CUDA device [%s]\n", deviceProps.name);
    int n = 16 * 1024 * 1024;
    int nbytes = n*sizeof(int);
    int value = 26;
    int *a = 0;
    cudaMallocHost((void**)&a, nbytes);
    memset(a, 0, nbytes);
    int *d_a = 0;
    cudaMalloc((void**)&d_a, nbytes);
    cudaMemset(d_a, 255, nbytes);
    dim3 threads = dim3(512, 1);
    dim3 blocks = dim3(n / threads.x, 1);

    cudaEvent_t startGPU, stopGPU;
    cudaEventCreate(&startGPU);
    cudaEventCreate(&stopGPU);

    StopWatchInterface *timer = NULL;
    sdkCreateTimer(&timer);
    sdkResetTimer(&timer);

    cudaThreadSynchronize();

    float gpu_time = 0.0f;


    sdkStartTimer(&timer);
    cudaEventRecord(startGPU, 0);
    cudaMemcpyAsync(d_a, a, nbytes, cudaMemcpyHostToDevice, 0);
    increment_kernel << <blocks, threads, 0, 0 >> >(d_a, value);
    cudaMemcpyAsync(a, d_a, nbytes, cudaMemcpyDeviceToHost, 0);
    cudaEventRecord(stopGPU, 0);
    sdkStopTimer(&timer);

    unsigned long int counter = 0;

    while (cudaEventQuery(stopGPU) == cudaErrorNotReady)
    {
        counter++;
    }

    cudaEventElapsedTime(&gpu_time, startGPU, stopGPU);
    printf("time spent executing by the GPU:%.2f\n", gpu_time);
    printf("time spent by CPU in CUDA calls:%.8f\n", sdkGetTimerValue(&timer));
    printf("GPU execute %d iteration while waiting forGPU to finish\n", counter);

    printf("-------------------------------------------------------------------------\n");
    if (correct_output(a, n, value))
        printf("TEST PASSED\n");
    else
        printf("Test FAILED\n");

    cudaEventDestroy(startGPU);
    cudaEventDestroy(stopGPU);
    cudaFreeHost(a);
    cudaFree(d_a);
    getchar();
    cudaThreadExit();
    return 0;
}

执行结果:
这里写图片描述
代码中
GPU上执行的是对每一个数据进行加26的处理,在CPU上执行加1迭代,
执行结果依次是GPU执行的时间,异步时CPU调用GPU所用的时间,以及在GPU上进行计算时CPU进行迭代的次数。

其中:
void *memset(void *s, int ch, size_t n);
函数解释:将s中前n个字节替换为ch并返回s;

memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法。

helper_timer.h在C:\ProgramData\NVIDIA Corporation\CUDA Samples\v7.5\common\inc下是在CUDA取消了cutil.h后包含计时的一个文件

cudaThreadSynchronize()函数是是CPU与GPU同步

目录
相关文章
|
4月前
|
开发框架 供应链 监控
并行开发模型详解:类型、步骤及其应用解析
在现代研发环境中,企业需要在有限时间内推出高质量的产品,以满足客户不断变化的需求。传统的线性开发模式往往拖慢进度,导致资源浪费和延迟交付。并行开发模型通过允许多个开发阶段同时进行,极大提高了产品开发的效率和响应能力。本文将深入解析并行开发模型,涵盖其类型、步骤及如何通过辅助工具优化团队协作和管理工作流。
123 3
|
3月前
|
机器学习/深度学习 数据采集 数据挖掘
Python编程语言的魅力:从入门到进阶的全方位解析
Python编程语言的魅力:从入门到进阶的全方位解析
|
3月前
|
存储 人工智能 安全
CPFS深度解析:并行文件存储加速AI创新
在生成式AI的大潮中,并行文件系统作为高性能数据底座,为AI算力提供高吞吐、低延迟的数据存储服务。在本话题中,我们将介绍阿里云并行文件存储CPFS针对AI智算场景而提供的产品能力演进与更新,深入讲解在性能、成本、稳定、安全等方面的技术创新。
246 0
|
3月前
|
存储 设计模式 分布式计算
Java中的多线程编程:并发与并行的深度解析####
在当今软件开发领域,多线程编程已成为提升应用性能、响应速度及资源利用率的关键手段之一。本文将深入探讨Java平台上的多线程机制,从基础概念到高级应用,全面解析并发与并行编程的核心理念、实现方式及其在实际项目中的应用策略。不同于常规摘要的简洁概述,本文旨在通过详尽的技术剖析,为读者构建一个系统化的多线程知识框架,辅以生动实例,让抽象概念具体化,复杂问题简单化。 ####
|
3月前
|
存储 弹性计算 NoSQL
"从入门到实践,全方位解析云服务器ECS的秘密——手把手教你轻松驾驭阿里云的强大计算力!"
【10月更文挑战第23天】云服务器ECS(Elastic Compute Service)是阿里云提供的基础云计算服务,允许用户在云端租用和管理虚拟服务器。ECS具有弹性伸缩、按需付费、简单易用等特点,适用于网站托管、数据库部署、大数据分析等多种场景。本文介绍ECS的基本概念、使用场景及快速上手指南。
123 3
|
4月前
|
机器学习/深度学习 人工智能 自然语言处理
前端大模型入门(三):编码(Tokenizer)和嵌入(Embedding)解析 - llm的输入
本文介绍了大规模语言模型(LLM)中的两个核心概念:Tokenizer和Embedding。Tokenizer将文本转换为模型可处理的数字ID,而Embedding则将这些ID转化为能捕捉语义关系的稠密向量。文章通过具体示例和代码展示了两者的实现方法,帮助读者理解其基本原理和应用场景。
906 1
|
4月前
|
存储 编译器 C语言
C++类与对象深度解析(一):从抽象到实践的全面入门指南
C++类与对象深度解析(一):从抽象到实践的全面入门指南
65 8
|
4月前
|
数据处理 Python
深入探索:Python中的并发编程新纪元——协程与异步函数解析
深入探索:Python中的并发编程新纪元——协程与异步函数解析
40 3
|
4月前
|
JSON JavaScript 前端开发
深入解析ESLint配置:从入门到精通的全方位指南,精细调优你的代码质量保障工具
深入解析ESLint配置:从入门到精通的全方位指南,精细调优你的代码质量保障工具
142 0
|
4月前
|
应用服务中间件 测试技术 nginx
Nginx入门 -- 解析Nginx中的基本概念:Keepalive
Nginx入门 -- 解析Nginx中的基本概念:Keepalive
176 0

推荐镜像

更多