cuda编程[3]:测试CPU,GPU预热,warp无分化和warp有分化

目录

前言

  所有的代码下载链接:code,在code/test_warp下能看到所有代码,包括.vscode,CMakeLists.txt,和.nsys-rep文件。所有代码和性能分析文件经过测试,可以运行。

配置文件

  .vscode目录下,这里需要大家自行修改,这里有四个文件。

//这是c_cpp_properties.json的代码,用于告诉我的vscode编译CUDA C++的代码的时候分别从workspaceFolder中的MSVC和CUDA安装目录下的NVCC。
{
    "configurations": [
        {
            "name": "Win32",
            "includePath": [
                "${workspaceFolder}/**",
                "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v12.1/include"
            ],
            "defines": [],
            "compilerPath": "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v12.1/bin/nvcc.exe",
            "intelliSenseMode": "windows-msvc-x64",
            "configurationProvider": "ms-vscode.cmake-tools"
        }
    ],
    "version": 4
}

下面就不一一列举代码了 可以自行从上面链接下载。

主函数

  main.cpp为整个代码逻辑。先是导入了所有的头文件,库等等,定义了一个全局变量seed。执行最后的可执行文件的时候需要输入size和block_size。代码下方已经放上运行后的结果。现在请从main.cpp一行一行阅读:

#include <iostream>
#include <stdio.h>
#include <cuda_runtime.h>
#include <string>
#include "utils.hpp" //错误检查函数的头文件
#include "timer.hpp" //记时函数
#include "reduce.hpp"//CPU上的分化函数
#include <cstring>
#include <memory>
#include <cmath>

int seed;
int main(int argc, char** argv)
{
    if (argc != 3)
    {
        std::cout << "Usage: ./build/reduction [size] [block_size]" << std::endl;//输出使用说明,告诉用户如何正确调用这个程序。
        return -1;
    }
    
    
    Timer timer;//timer类实例化
    char str[100];
    int size       = std::stoi(argv[1]);
    int block_size = std::stoi(argv[2]);
    int grid_size  = size / block_size;

    float* h_idata = nullptr;
    float* h_odata = nullptr;
    h_idata = (float*)malloc(size * sizeof(float));
    h_odata = (float*)malloc(grid_size * sizeof(float));
    
    seed = 1;
    initMatrix(h_idata, size, seed);
    memset(h_odata, 0, grid_size * sizeof(float));

    // CPU Reduction
    timer.start_cpu();
    float sumOnCPU = ReduceOnCPU(h_idata, size);
    timer.stop_cpu();
    std::sprintf(str, "reduce in cpu, results: %f", sumOnCPU);
    timer.duration_cpu<Timer::ms>(str);

    //GPU warmup
    timer.start_gpu();
    ReduceOnGPUWithDivergence(h_idata, h_odata, size, block_size);
    timer.stop_gpu();
    // timer.duration_gpu<Timer::ms>("reduce in gpu warmup");

    //GPU Reduction with Divergence
    timer.start_gpu();
    ReduceOnGPUWithDivergence(h_idata, h_odata, size, block_size);
    timer.stop_gpu();
    float sumOnGPUWithDivergence = 0;
    for (int i = 0; i < grid_size; i++)
    {
        sumOnGPUWithDivergence += h_odata[i];
    }
    std::sprintf(str, "reduce in gpu with divergence, results: %f", sumOnGPUWithDivergence);
    timer.duration_gpu(str);

    //GPU Reduction without Divergence
    timer.start_gpu();
    ReduceOnGPUWithoutDivergence(h_idata, h_odata, size, block_size);
    timer.stop_gpu();
    float sumOnGPUWithoutDivergence = 0;
    for (int i = 0; i < grid_size; i++)
    {
        sumOnGPUWithoutDivergence += h_odata[i];
    }
    std::sprintf(str, "reduce in gpu without divergence, results: %f", sumOnGPUWithoutDivergence);
    timer.duration_gpu(str);

    free(h_idata);
    free(h_odata);
    return 0;
}

/******************************************************************
(joker) PS C:\Users\22681\Desktop\project\cudalearn\notes\code\test_warp> ./build/Debug/reduction.exe 33554432 512
reduce in cpu, results: 16777216.000000  uses 52.933100 ms
reduce in gpu with divergence, results: 16779780.000000      uses 19.392063 ms
reduce in gpu without divergence, results: 16779780.000000   uses 18.935841 ms
 *****************************************************************/

  其中记时,错误检查函数(我的上一篇文章中有说过)的头文件分别在timer.hpp和utils.hpp,可以去查看代码看到里面声明的函数具体是什么。接下来就是如何编译这个main.cpp。

编译

  可以看到我的代码目录中有CMakeLists.txt文件,这里就是使用cmake构建整个项目。.接下来看代码:

cmake_minimum_required(VERSION 3.18)
# 项目信息
project(ReductionComputation LANGUAGES CXX CUDA)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CUDA_STANDARD 14) # 用于指定CUDA编译器应该使用的CUDA C++标准的版本
set(CMAKE_CUDA_STANDARD_REQUIRED ON)    # 表明如果找不到指定版本的CUDA编译器,将发出错误
set(CMAKE_CXX_STANDARD 14)  # 用于指定 C++ 编译器应该使用的 C++ 标准版本
set(CMAKE_CXX_STANDARD_REQUIRED ON) # 表明如果找不到指定版本的 C++ 编译器,将发出错误

find_package(CUDAToolkit REQUIRED)  # 查找 CUDA 库
if(CUDAToolkit_FOUND)
    message(STATUS "Found CUDA ${CUDA_VERSION_STRING} at ${CUDA_TOOLKIT_ROOT_DIR}")
    message(STATUS "CUDA_INCLUDE_DIRS: ${CUDA_INCLUDE_DIRS}")
    message(STATUS "CUDA_LIBRARIES: ${CUDA_LIBRARIES}")
    message(STATUS "CUDA_LIBRARY_DIRS: ${CUDA_LIBRARY_DIRS}")
else()
message(FATAL_ERROR "Cannot find CUDA")
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    set(CMAKE_CUDA_FLAGS_DEBUG "-G -g -O0 -arch=sm_86")   # CUDA Debug
    set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")                    # C++ Debug
else()
    set(CMAKE_CUDA_FLAGS_RELEASE "-O3 -arch=sm_86")       # CUDA Release
    set(CMAKE_CXX_FLAGS_RELEASE "-O3")                    # C++ Release
endif()

file(GLOB_RECURSE SRCS ${PROJECT_SOURCE_DIR}/src/*.cpp ${PROJECT_SOURCE_DIR}/src/*.cu)
set(INC "${PROJECT_SOURCE_DIR}/inc")
# 添加可执行文件
add_executable(reduction ${SRCS})
target_include_directories(reduction PRIVATE ${INC})
target_include_directories(reduction PRIVATE ${CUDA_INCLUDE_DIRS})
# 链接库
target_link_libraries(reduction PRIVATE ${CUDA_LIBRARIES})

代码指定了cmake版本,代码是CUDA C++,告诉了项目去哪里找CUDA的包,以及编译时的cpp,hpp,cu都在哪个目录下等等,cmake的语法不过多介绍。
  接下来就是正式编译,接下来几步我的专栏中有说明,是如何使用vscode配置CUDA C++编译环境并运行的。这里第三次输入的是执行编译完成后的ereduction可执行文件,这个可执行文件需要输入参数33554432和512。

cmake -B build -G "Visual Studio 16 2019"
cmake --build build
./build/Debug/reduction.exe 33554432 512

此时可以看到程序正确输出了结果。接下来我们使用nvidia提供的nsight system(当你下载了CUDA后你的windows开始菜单栏可以搜到这个附带的性能分析工具),这个工具替代了之前的nvprof。
在这里插入图片描述

性能分析

  前面的步骤如果都没有错的话,现在进入到最后一步,对GPU执行main程序的性能进行更加详细的分析。找到编译后的可执行文件,在这个.exe文件的目录下使用管理员运行powershell,然后输入指令:

nsys profile --stats=true ./reduction.exe 33554432 512

nsys就是性能分析的nsight system,然后分析这个可执行程序,并带上这两个参数。稍等片刻会看到进度100%并返回.nsys-rep和.splite文件。
在这里插入图片描述
点击第一个nsys-rep会出现可视化界面便可以详细看到每个线程执行的时间。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小马敲马

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值