前往我的主页以获得更好的阅读体验C#的GPU加速方法 - DearXuan的主页https://blog.dearxuan.com/2021/08/13/C-%E7%9A%84GPU%E5%8A%A0%E9%80%9F%E6%96%B9%E6%B3%95/

本文将通过C#调用dll的方法来实现并发计算

在VS2019里新建动态链接库项目,在pch.h里定义函数

// pch.h: 这是预编译标头文件。
// 下方列出的文件仅编译一次,提高了将来生成的生成性能。
// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。
// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。#ifndef PCH_H
#define PCH_H// 添加要在此处预编译的标头
#include "framework.h"
extern "C" _declspec(dllexport) void Sum(int* s,int a[],int b[],int length);#endif //PCH_H

在pch.cpp里实现该函数

// pch.cpp: 与预编译标头对应的源文件#include "pch.h"
#include <amp.h>// 当使用预编译的头时,需要使用此源文件,编译才能成功。using namespace Concurrency;extern "C" _declspec(dllexport) void Sum(int* s, int a[], int b[],int length) {array_view<const int, 1> aArray(length, a);array_view<const int, 1> bArray(length, b);array_view<int, 1> sum(length, s);parallel_for_each(sum.extent,[=](index<1> idx) restrict(amp) {sum[idx] = aArray[idx] + bArray[idx];});
}

该函数接收4个参数,分别用来储存结果,a数组,b数组,数组长度,并将a和b数组相加,结果储存在s里面。

array_view表示包含在一个容器中的数据的N维视图,各项参数的含义如下:

const int:类型,

1:维数

aArray:array_view的实例

length:长度

a:数据源

如果是二维数组,则要改成下面的形式

array_view<const int, 2> aArray(width,height, a);

parallel_for_each语句能够进行并发计算,index<1>指idx是一维的,如果是二维数组,需要改成index<2>,此时idx相当于(i,j),通过idx[0]和idx[1]获得行号和列号

例如

int row = idx[0];
int col = idx[1];

aArray[idx]和aArray(row,col)是等效的

将上述代码生成dll,并放在C#程序的目录下

导入刚刚写的dll

[DllImport("Dll1.dll", EntryPoint = "Sum", CallingConvention = CallingConvention.Cdecl)]
public static extern void Sum(IntPtr s,int[] a, int[] b,int length);

生成随机数数组,求和

static void Main(string[] args)
{const int size = 100;int[] s = new int[size];int[] a = new int[size];int[] b = new int[size];Random random = new Random();for(int i = 0; i < size; i++){a[i] = random.Next(0, 100);b[i] = random.Next(100, 200);}unsafe{IntPtr p = Marshal.UnsafeAddrOfPinnedArrayElement(s, 0);Sum(p, a, b, size);}for(int i = 0; i < size; i++){Console.WriteLine(a[i] + "+" + b[i] + "=" + s[i]);}Console.ReadLine();
}

使用StopWatch类来计算耗时(命名空间System.Diagnostics)

Stopwatch watch1 = new Stopwatch();
watch1.Start();
for(int i = 0; i < size; i++)
{s[i] = a[i] + b[i];
}
watch1.Stop();
Console.WriteLine("CPU耗时:" + watch1.Elapsed.TotalMilliseconds);
Stopwatch watch2 = new Stopwatch();
watch2.Start();
Sum(p, a, b, size);
watch2.Stop();
Console.WriteLine("GPU耗时:" + watch2.Elapsed.TotalMilliseconds);

由于加载dll本身需要时间,所以在计时之前需要先调用一次Sum函数。

测试代码是计算4亿个数的和,可以看到GPU计算比CPU计算少了300毫秒,但是CPU在循环2亿次的情况下居然仅仅比GPU多了300毫秒,这是因为GPU无法从内存读取数据,需要把数据先复制到显存里才能计算,计算完又需要把数据复制回来,而主要时间开销都在数据的复制里面。

现实情况下,循环体里不可能只有一行代码,假设循环体里有10个语句,那么CPU的执行时间就会翻10倍,而GPU的执行时间也会翻10倍,但是由于主要耗时操作是数据的复制,所以实际增长不会特别明显。

下面我们修改一下代码。

extern "C" _declspec(dllexport) void Sum(int* s, int a[], int b[],int length) {array_view<const int, 1> aArray(length, a);array_view<const int, 1> bArray(length, b);array_view<int, 1> sum(length, s);parallel_for_each(sum.extent,[=](index<1> idx) restrict(amp) {sum[idx] = aArray[idx] + bArray[idx];if (idx[0] % 5 == 0) {sum[idx] += 5;}if (idx[0] % 7 == 0) {sum[idx] += 7;}if (idx[0] % 11 == 0) {sum[idx] += 11;}if (idx[0] % 13 == 0) {sum[idx] += 13;}if (idx[0] % 17 == 0) {sum[idx] += 17;}});
}
watch1.Start();
for(int i = 0; i < size; i++)
{s[i] = a[i] + b[i];if (i % 5 == 0){s[i] += 5;}if (i % 7 == 0){s[i] += 7;}if (i % 11 == 0){s[i] += 11;}if (i % 13 == 0){s[i] += 13;}if (i % 17 == 0){s[i] += 17;}
}
watch1.Stop();
Console.WriteLine("CPU耗时:" + watch1.Elapsed.TotalMilliseconds);

这次改用100万量级的数据

现在GPU的优势就完全体现出来了

C#的GPU加速方法相关推荐

  1. Pytorch gpu加速方法

    Pytorch gpu加速方法 原文: https://www.zhihu.com/question/274635237 relu 用 inplace=True 用 eval() 和 with tor ...

  2. ae怎么设置gpu渲染_AECS6 显卡GPU加速方法

    显卡 GPU 加速方法 显卡 GPU 加速在预览高清素材和加入特效的时候,可以加快预览速度,做到比较好的即 时预览.会有人问开启 GPU 为什么会加速呢?简单来说,就是显卡自带了内存,会自行去进 行运 ...

  3. Matlab之GPU加速方法

    Matlab之GPU加速方法 Matlab之GPU加速方法 一般代码加速方法 GPU设备确认 GPU和CPU之间数据传递 复杂代码加速方法 一般代码加速方法 Matlab目前只支持Nvidia的显卡. ...

  4. pytorch采用GPU加速方法

    在进行深度学习训练模型时,对于计算量小一些的模型,是可以在CPU上进行的.但是当计算量比较大时,我们希望利用GPU并行计算的能力去加快训练的速度. 查看GPU版本号 import torchprint ...

  5. matlab 中使用 GPU 加速运算

    为了提高大规模数据处理的能力,matlab 的 GPU 并行计算,本质上是在 cuda 的基础上开发的 wrapper,也就是说 matlab 目前只支持 NVIDIA 的显卡. 1. GPU 硬件支 ...

  6. 【PyTorch教程】P30 GPU加速

    P30 GPU加速 调用 GPU的两种方法: 1.调用 .cuda() 在这三个内容后面,加上 .cuda()方法 下图中,在原来的三种内容上,分别加上.cuda( ),就可以了:让他们的返回值,继续 ...

  7. 新版本GPU加速的tensorflow库的配置方法

      本文介绍在Anaconda环境中,配置可以用GPU运行的Python新版tensorflow库的方法.   在上一篇文章Anaconda配置Python新版本tensorflow库(CPU.GPU ...

  8. matlab win10 gpu加速,win10怎么开启gpu加速有用吗 GPU硬件加速设置方法介绍

    win10怎么开启gpu加速有用吗 GPU硬件加速设置方法介绍 作为Windows 10的一项重要功能,微软在分享了GPU硬件加速细节后,现在还为大家送上了开启它的技巧,对于中低端设备来说,提升效果还 ...

  9. 强制开启Android Webview GPU 加速的方法

    强制开启Android Webview GPU 加速的方法 常用方法 浏览器开启GPU加速可以让渲染的性能更好,可以有效的利用硬件的能力来提高页面的绘制帧率.在安卓平台使用webview的场景下,开发 ...

最新文章

  1. boost::compressed_sparse_row_graph用法的测试程序
  2. php在线语音,PHP在线语音合成
  3. 表级锁的mysql读写_Mysql的表级锁
  4. 深入理解java虚拟机 (一) 第二版
  5. STM32(五)------GPIO位带操作
  6. FatFs - Generic FAT Filesystem Module
  7. java 最接近_Java在集合中查找最接近(或相等)的值
  8. Codeforces Round #544 (Div. 3) A.Middle of the Contest
  9. 邮件服务器搬家,企业邮箱怎么“搬家”
  10. Onvif协议快速入门
  11. 最新《圣思园JavaSE实地培训系列教程》
  12. 用sql获取当前年月日YEAR(GETDATE()), MONTH(GETDATE()),DAY(GETDATE())
  13. thinkphp + 腾讯云名片识别
  14. opengl画圆柱体、圆锥等并使用四元数旋转
  15. 基于Webmagic的爬取B站用户数据的爬虫
  16. cacti 介绍
  17. 《微信公众平台与小程序开发——从零搭建整套系统》——第1章,第1.2节微信公众平台...
  18. 用友BIP产品矩阵亮相首届中小企业数字化转型大会,数智创新驱动企业高效成长
  19. 发布有礼!2015 Autodesk程序商店有奖发布活动拉开序幕
  20. 04 Anykey右分页布局TableLayout

热门文章

  1. [sudo rm -rf /bin/] Linux误删除/bin目录恢复
  2. 读《Jonathan von Neumann and EDVAC》
  3. 医院信息管理系统(Python与MySQL数据库的连接与相关增删改查操作)
  4. java poi 导入报错,Cannot get a NUMERIC value from a STRING cell
  5. MySQL连接、SSL加密与密码插件
  6. android pc扩展屏幕分辨率,让闲置的iPad / Android平板电脑成为计算机屏幕的扩展显示!...
  7. 解决linux看温度是报错No sensors found问题
  8. uniapp 安卓证书生成
  9. 单片机电流检测电路图大全(四款模拟电路设计原理图详解) - 信号处理电子电路图
  10. R和RStudio安装包下载