cuda与cpu高斯列主消元求解线性方程组速度比较

2023-11-10

cuda与cpu高斯列主消元求解线性方程组速度比较

 

  最近看了看cuda上面用c语言进行的编程,踩了很多的坑,在这里记录一下。

  完整程序已上传:https://download.csdn.net/download/qq_41910473/12917838

  配置环境:VS2017  cuda10.0  Runtime,cpu:i5 8600K ,显卡:GTX 1060

  求解公式是:A*x = b,   A: N*N方阵,x:N维列向量,b: N维列向量,求解未知量x向量。

      求解方法:分别在gpu与cpu上进行高斯列主消元,比较运行的时间。

  求解的过程分为三步:

                               1、求最大值进行行交换。

                               2、消元。

                               3、回代。

   程序分为两部分,第一部分用cuda实现,第二部分在cpu实现,并分别统计运行时间。最终得出结论当矩阵维度大于1000时GPU运行速度快于CPU,而当矩阵维度小于等于1000时GPU运行速度慢于CPU。程序中有很多地方可以进行优化例如使用共享内存、线程块的分配,由于题主只是证明CUDA在解线性方程可以进行加速所以就没有进行更细节的优化。

最终得出的结论:数据规模较小的话,例如:100*100线性方程组GPU并行求解速度远低于CPU迭代求解速度。数据规模较大,例如:2000*2000的线性方程组求解在GPU上可以得到显著的加速效果。

   cuda程序:

   __global__ void GaussKernelA(),单线程执行该函数来求解第k步时第k列的最大值并把该最大值所在的行交换到第k行。

__global__ void GaussKernelA(double *augmentedMatrixGPU, int k, int n) {    //K :消元第k步,n:增广矩阵的行数
	int i = blockIdx.x * blockDim.x + threadIdx.x;
	int j = blockIdx.y * blockDim.y + threadIdx.y;

	int s;
	double temp, r;

	if (i == 0 && j == 0) {  //限定只有单线程执行该核函数
		s = k;
		r = fabs(augmentedMatrixGPU[k*(n + 1) + k]);
		for (int i = k; i < n; i++) {
			if (r < fabs(augmentedMatrixGPU[i*(n + 1) + k])) {
				r = fabs(augmentedMatrixGPU[i*(n + 1) + k]);
				s = i;
			}
		}
		if (s != k) {   //交换矩阵的两行
			Change(augmentedMatrixGPU + k * (n + 1), augmentedMatrixGPU + s * (n + 1), n);
		}
	}
}

 __global__ void augmented(),__global__ void GaussKernelB,高斯消元。

__global__ void augmented(double *augmentedMatrixGPU, int k, int n) {
	int i = blockIdx.x * blockDim.x + threadIdx.x;
	int j = blockIdx.y * blockDim.y + threadIdx.y;

	if (i == j && j > k && j < n  && augmentedMatrixGPU[k * (n + 1) + k] != 0) {
		augmentedMatrixGPU[j * (n + 1) + k] = augmentedMatrixGPU[j * (n + 1) + k] / augmentedMatrixGPU[k * (n + 1) + k];
	}

}

 

__global__ void GaussKernelB(double *augmentedMatrixGPU, int k, int n) {
	int i = blockIdx.x * blockDim.x + threadIdx.x;
	int j = blockIdx.y * blockDim.y + threadIdx.y;

	if (i > k && i < n + 1 && j > k && j < n  && augmentedMatrixGPU[k * (n + 1) + k] != 0) {
		augmentedMatrixGPU[j * (n + 1) + i] = augmentedMatrixGPU[j * (n + 1) + i] -
			augmentedMatrixGPU[j * (n + 1) + k] *
			augmentedMatrixGPU[k * (n + 1) + i];
	}
}

    所有的核函数都用的是一维数组进行数据的存储,并把Ax = b,A与b进行合并以增广矩阵的形式进行存储。先用cudaMemcpy把数据从CPU 拷贝到GPU,再用cudaDeviceSynchronize()进行GPU线程同步然后在开始计时,在CPU  for循环中进行逻辑控制,把矩阵的消元与计算放到GPU中执行。(坑1:在计时停止前一定要加cudaDeviceSynchronize(),因为CPU与GPU是异步执行的,在for循环结束时GPU的可能仍在执行,若不加同步函数,计时函数(QueryPerformanceCounter(&stop))就会在GPU没有运行完之前就停止计时,导致时间不准确我当时不加同步函数,计时为:0.02ms左右,加同步函数,计时为:1.5ms)。本次计算只进行消元的计时,回代是在CPU上完成的。

cudaMemcpy(augmentedMatrixGPU, augmentedMatrix, sizeof(double)* n * (n + 1), cudaMemcpyHostToDevice);

	cudaDeviceSynchronize();
	QueryPerformanceCounter(&start);
	for (int k = 0; k < n - 1; k++) {
		GaussKernelA << <1, 1 >> > (augmentedMatrixGPU, k, n);
		augmented << <gridDim, blockDim >> > (augmentedMatrixGPU, k, n);
		GaussKernelB << <gridDim, blockDim >> > (augmentedMatrixGPU, k, n);
	}
	cudaDeviceSynchronize();
	QueryPerformanceCounter(&stop);
	time = 1000 * (stop.QuadPart - start.QuadPart) / frequence;
	printf("GPU time is : %fms", (time));

	cudaMemcpy(augmentedMatrix, augmentedMatrixGPU, sizeof(double)* n * (n + 1), cudaMemcpyDeviceToHost);

CPU:高斯消元程序

QueryPerformanceCounter(&sta);  //计时开始
	for (int k = 0; k < n - 1; k++) {
		max = fabs(d[k][k]);
		cols = k;
		for (int i = k; i < n; i++) {   //求最值
			if (max < fabs(d[i][k])) {
				max = fabs(d[i][k]);
				cols = i;
			}
		}
		if (cols != k) {  //交换行
			for (int j = k; j <= n; j++) {
				temp = d[cols][j];
				d[cols][j] = d[k][j];
				d[k][j] = temp;
			}
		}
		if (!d[k][k]) {
			printf("err------------------------------------\n");
			return -1;
		}
		for (int p = k + 1; p < n; p++) {    //消元
			d[p][k] = d[p][k] / d[k][k];
			for (int h = k + 1; h <= n; h++) {
				d[p][h] = d[p][h] - d[k][h] * d[p][k];
			}
		}
	}
	x[n - 1] = d[n - 1][n] / d[n - 1][n - 1];    //回代
	for (int i = n - 2; i >= 0; i--) {
		s = d[i][n];
		for (int j = i + 1; j <= n; j++) {
			s = s - x[j] * d[i][j];
		}
		x[i] = s / d[i][i];
	}
	QueryPerformanceCounter(&sto);  //计时结束
	time2 = 1000 * (sto.QuadPart - sta.QuadPart) / frequence;
	printf("CPU time is : %fms\n", time2);

运行时间比较:

矩阵:1000*1000

         

矩阵: 1500*1500

         

矩阵: 2000*2000

        

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

cuda与cpu高斯列主消元求解线性方程组速度比较 的相关文章

  • Linux--进程间通信、IPC、管道

    目录 1 进程间通信的方法 2 IPC机制 1 有命管道 1 简介 5 管道的特点 6 循环写读 2 无名管道 1 简介 2 代码 4 总体特点 5 管道实现图 1 进程间通信的方法 1 管道 2 信号量 3 共享内存 4 消息队列 5 套
  • java - jdwp远程调试线协议的使用

    前言 线上服务器出现的bug 因为各种复杂环境的原因 经常会很难在本地调试 只能到处打log 然后去服务器查看log日志 以定位问题产生原因 是否一工具能像idea中本地debug一样能直接断点调试呢 介绍 JDWP Java Debug

随机推荐

  • 华为上机考试注意事项及编程技巧(精品)

    这是一篇关于华为招聘软件类职位上机考试的博客 主要介绍一下华为机考的流程 注意事项以及一些机试题中常用的编程技巧 写得有点长 但都是尽心尽力敲的 如果真的要参加华为招聘 或者类似公司的招聘 建议稍微花点时间看完 话不多说 直接进入正题 一
  • 我对维度建模和范式建模的一点理解

    谈维度建模和范式建模之前 先了解下模型设计的三个阶段吧 概念模型 将业务划分成几个主题 逻辑模型 定义各种实体 属性 关系 物理模型 设计数据对象的物理实现 比如表的命名规范 字段的命名规范 字段类型等 一 范式建模 我先来介绍一下范式 范
  • 思维的特点和缺陷

    人类总是喜欢歌颂自己的大脑 比如 思想的威力 逻辑的威力 数学的威力 数学来自于思考 科学的威力 科学来源于思考 还有 意识 这个 人类与动物最大的区别 i blah blah 不过 几乎没有人关心过这种想法究竟来自于人体的哪个器官 心理学
  • 海思3559 安装

    设置地址 开机后任意键 进入 u boot 界面显示 hisilicon 以下内容转自 海思开发记录 一 3559A开发环境搭建 whitefish520的博客 CSDN博客 海思3559a 说明 这次安装的是Ubuntu14 04 64位
  • java8 lambda 获取list对象中重复数据

    工作上的场景 简单记录一下 在这里直接借用业务上的list 不再new 了 List
  • 前台模糊查询中用“\%”替换字符串中的“%”

    最近在做电商项目 前端开发好后就丢给我们 用的时候发现一个缺陷 前台模糊查询的时候 输入一个 或者包含 的词 查询的时候不准确 解决过程中第一个问题 前端用了Js的 decodeURL 转码 将前台输入的 转码了 无法传到后台 参考 htt
  • Java前端知识HTML

    Java前端知识 首先我们用的是HBuilderX软件 当然 前端知识有很多 如果有遗忘或者需要查询的可以去菜鸟驿站查询 比较全 html的文档结构主要是有三部分组成的 1 标记用于html文件的最前面 用来表示html文件的开始 而的标记
  • QSignalMapper信号映射器的使用

    目录 QSignalMapper介绍 Signal 信号 slots 根据标识获取对象 给对象设置标识 删除映射 实例 代码 需求升级 总结 相关文章 QSignalMapper介绍 该类收集一组无参数的信号 并使用与发送信号的对象对应的整
  • 不限时长,免费制作

    在这个信息爆炸的时代 短视频已经崭露头角 成为人们获取信息 娱乐和学习的首选渠道 事实上 大部分互联网用户每天都沉浸在短视频的世界中 这无疑证明了短视频营销的巨大潜力和不可替代的地位 2023年的数据进一步印证了这一点 中国短视频用户规模已
  • 页面禁止长按保存图片和长按复制文字

    1 禁止长按保存图片 img pointer events none 禁止none 启用auto Tips pointer events属性详解 官方文档 https www html cn book css properties user
  • 面试题 01.06. 字符串压缩

    字符串压缩 利用字符重复出现的次数 编写一种方法 实现基本的字符串压缩功能 比如 字符串aabcccccaaa会变为a2b1c5a3 若 压缩 后的字符串没有变短 则返回原先的字符串 你可以假设字符串中只包含大小写英文字母 a至z 示例1
  • 找出数组中的最大有序子数组

    效率O n m import java util HashSet import java util Set public class FindLongestArray public static void main String args
  • 第十四届蓝桥杯单片机第二场模拟赛程序(AD+字符接受串口)

    完整代码 include
  • MIPI介绍(CSI DSI接口)

    MIPI Mobile Industry Processor Interface 是2003年由ARM Nokia ST TI等公司成立的一个联盟 目的是把手机内部的接口如摄像头 显示屏接口 射频 基带接口等标准化 从而减少手机设计的复杂程
  • 解决“AD中设置板子区域时候遇到的找不到闭合形状”问题

    问题说明 今天给大家分享一下 我们在画PCB时候有时候会想将PCB设置区域改为自己板子的大小 就是整个区域就只有自己的板子 大家不明白的话 可以看看下面这张图 或许就明白了 对于如何将PCB区域改为我们板子的形状 可以参考我这篇文章 这里我
  • web3j的基础用法-3ETH交易监听器

    ETH的交易监听器 demo简单实现了4种 监听区块 public Subscription subscribeBlock final Action1
  • 玩客云armbian刷机教程

    文章作者 GoodBoyboy 文章链接 https blog goodboyboy top posts 3292274545 html 版权声明 本博客所有文章除特别声明外 均采用 CC BY NC SA 4 0 许可协议 转载请注明来自
  • 【机器学习实战】4、基于概率论的分类方法:朴素贝叶斯

    文章目录 4 1 基于贝叶斯决策理论的分类方法 4 1 1 贝叶斯决策理论 4 1 2 条件概率 4 1 3 全概率公式 4 1 4 贝叶斯推断 4 1 5 朴素贝叶斯 4 2 使用朴素贝叶斯进行文档分类 4 3 总结 4 4 朴素贝叶斯改
  • QT+VS2019 环境搭建

    一 概述 一个PC QT 的跨平台项目要维护 需要搭建一套环境 使用的是QT VS2019的环境 QT使用v5 9 3的版本 这个版本qalgorithms h文件要替换成新的 源码附在文尾 vs插件使用qt vsaddin msvc201
  • cuda与cpu高斯列主消元求解线性方程组速度比较

    cuda与cpu高斯列主消元求解线性方程组速度比较 最近看了看cuda上面用c语言进行的编程 踩了很多的坑 在这里记录一下 完整程序已上传 https download csdn net download qq 41910473 12917