CUDA -- 规约求矩阵的行和
求矩阵每行的和?
可以把每行放入一个不同线程块,这样行与行之间进行粗粒度的并行。而对于每行,其对应的线程块中分配n个线程(对应行宽),使用共享存储器,让每个线程从显存中读取一个数至shared memory中,然后使用规约算法计算和。
代码如下:
#include "cuda_runtime.h" //CUDA运行时API
#include "device_launch_parameters.h"
#include <iostream>
#include <stdio.h> cudaError_t addWithCuda(int mat[][], int *ans, dim3 d); __global__ void addKernel(int *mat, int *ans, size_t pitch)
{
int bid = blockIdx.x;
int tid = threadIdx.x;
__shared__ int data[];
int *row = (int*)((char*)mat + bid*pitch);
data[tid] = row[tid];
__syncthreads();
for (int i = ; i > ; i /= ) {
if (tid < i)
data[tid] = data[tid] + data[tid + i];
__syncthreads();
}
if (tid == )
ans[bid] = data[];
} int main()
{
const int row = ;
const int col = ;
dim3 d(col, row);
int mat[row][col] = { ,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,, };
int ans[row];
// Add vectors in parallel.
cudaError_t cudaStatus = addWithCuda(mat, ans, d);
if (cudaStatus != cudaSuccess)
{
fprintf(stderr, "addWithCuda failed!\n");
return ;
}
// cudaThreadExit must be called before exiting in order for profiling and
// tracing tools such as Nsight and Visual Profiler to show complete traces.
cudaStatus = cudaThreadExit();
if (cudaStatus != cudaSuccess)
{
fprintf(stderr, "cudaThreadExit failed!");
return ;
}
for (int i = ; i < d.y; i++)
{
std::cout << ans[i] << " ";
}
return ;
} // 重点理解这个函数
cudaError_t addWithCuda(int mat[][], int *ans, dim3 d)
{
int *dev_mat = ; //GPU设备端数据指针
int *dev_ans = ;
int pitch;
cudaError_t cudaStatus; //状态指示
// Choose which GPU to run on, change this on a multi-GPU system.
cudaStatus = cudaSetDevice(); //选择运行平台
if (cudaStatus != cudaSuccess)
{
fprintf(stderr, "cudaSetDevice failed! Do you have a CUDA-capable GPU installed?");
goto Error;
}
// 分配GPU设备端内存
cudaStatus = cudaMallocPitch((void**)&dev_mat, (size_t *)&pitch, d.x * sizeof(int), d.y);
if (cudaStatus != cudaSuccess)
{
fprintf(stderr, "cudaMalloc failed!\n");
goto Error;
}
cudaStatus = cudaMalloc((void**)&dev_ans, d.y * sizeof(int));
if (cudaStatus != cudaSuccess)
{
fprintf(stderr, "cudaMalloc failed!\n");
goto Error;
}
// 拷贝数据到GPU
cudaStatus = cudaMemcpy2D(dev_mat, pitch, mat, d.x*sizeof(int), d.x*sizeof(int), d.y, cudaMemcpyHostToDevice);
if (cudaStatus != cudaSuccess)
{
fprintf(stderr, "cudaMemcpy for dev_mat failed!\n");
goto Error;
}
cudaStatus = cudaMemcpy(dev_ans, ans, d.y * sizeof(int), cudaMemcpyHostToDevice);
if (cudaStatus != cudaSuccess)
{
fprintf(stderr, "cudaMemcpy for dev_ans failed!\n");
goto Error;
}
// 运行核函数
cudaEvent_t start, stop;
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord(start, );
addKernel<<<d.y,d.x>>>(dev_mat, dev_ans, pitch);
//addKernel_thd << <1, size >> >(dev_c, dev_a, dev_b); cudaEventRecord(stop, );
cudaEventSynchronize(stop);
float tm;
cudaEventElapsedTime(&tm, start, stop);
printf("GPU Elapsed time:%.6f ms.\n", tm);
// cudaThreadSynchronize waits for the kernel to finish, and returns
// any errors encountered during the launch.
cudaStatus = cudaThreadSynchronize(); //同步线程
if (cudaStatus != cudaSuccess)
{
fprintf(stderr, "cudaThreadSynchronize returned error code %d after launching addKernel!\n", cudaStatus);
goto Error;
}
// Copy output vector from GPU buffer to host memory.
cudaStatus = cudaMemcpy(ans, dev_ans, d.y * sizeof(int), cudaMemcpyDeviceToHost); //拷贝结果回主机
if (cudaStatus != cudaSuccess)
{
fprintf(stderr, "cudaMemcpy failed!");
goto Error;
}
Error:
cudaFree(dev_mat); //释放GPU设备端内存
cudaFree(dev_ans);
return cudaStatus;
}
CUDA -- 规约求矩阵的行和的更多相关文章
- POJ 1151 Atlantis(经典的线段树扫描线,求矩阵面积并)
求矩阵的面积并 采用的是区间更新 #include <iostream> #include <stdio.h> #include <string.h> #inclu ...
- HDU 1828 / POJ 1177 Picture (线段树扫描线,求矩阵并的周长,经典题)
做这道题之前,建议先做POJ 1151 Atlantis,经典的扫描线求矩阵的面积并 参考连接: http://www.cnblogs.com/scau20110726/archive/2013/0 ...
- MATLAB中求矩阵非零元的坐标
MATLAB中求矩阵非零元的坐标: 方法1: index=find(a); [i,j]=ind2sub(size(a),index); disp([i,j]) 方法2: [i,j]=find(a> ...
- POJ 1151 Atlantis 求矩阵面积并 扫描线 具体解释
题意: 给定n个矩阵的左下角和右上角坐标,求矩阵面积并(矩阵总是正放的,即与x轴y轴都平行) 思路: 扫描线裸题 http://www.cnblogs.com/fenshen371/p/3214092 ...
- 求矩阵中各列数字的和 Exercise08_01
import java.util.Scanner; /** * @author 冰樱梦 * 时间:2018年12月 * 题目:求矩阵中各列数字的和 * */ public class Exercise ...
- 求矩阵主对角线元素的和 Exercise08_02
import java.util.Scanner; /** * @author 冰樱梦 * 时间:2018年12月 * 题目:求矩阵主对角线元素的和 * */ public class Exercis ...
- matlab求矩阵、向量的模
求矩阵的模: function count = juZhenDeMo(a,b) [r,c] = size(a);%求a的行列 [r1,c1] = size(b);%求b的行列 count = 0; f ...
- JAVA 基础编程练习题29 【程序 29 求矩阵对角线之和】
29 [程序 29 求矩阵对角线之和] 题目:求一个 3*3 矩阵对角线元素之和 程序分析:利用双重 for 循环控制输入二维数组,再将 a[i][i]累加后输出. package cskaoyan; ...
- 市场清仓价格算法 python求矩阵不同行不同列元素和的最大值
问题描述 求矩阵不同行不同列元素和的最大值(最小值) 问题求解 1.通过scipy库求解 scipy.optimize库中的linear_sum_assignment方法可以求解 输入一个矩阵,参数m ...
随机推荐
- 使用VSCode创建一个Vue项目
vue-cli 是vue.js的脚手架,用于自动生成vue.js模板工程的. 安装vue-cli之前,需要先安装了vue和webpack · node -v //(版本低引起:bas ...
- linux学习(五)用户与组管理命令,以及用户信息文件解释
目录 (1)/etc/passwd文件 (2)/etc/shadow passwd命令 userdel命令 usermod命令 groupadd @(用户与组管理命令) linux是一个多用户多任务的 ...
- 37-Data Volume 之 bind mount
storage driver 和 data volume 是容器存放数据的两种方式,上一节我们学习了 storage driver,本节开始讨论 Data Volume. Data Volume 本质 ...
- Unity如何更改精灵中心点
Unity虽然可以改中心点但是仅支持几个特定位置. 如果是一个你是切割的精灵,则可以进入精灵编辑器中调整 打开精灵编辑器后按调整如下图所示的pivot选项,我在这里把精灵调整成了右上. 在精灵编辑 ...
- Less(4)
1.先判断注入类型 (1)首先看到要求,要求传一个ID参数,并且要求是数字型的:?id=1 (2)再输入?id=1' 界面无变化 (3)再输入?id=1'' 界面还是无变化, (4)再输入?id=1 ...
- 提取Office图标的方法
需求 几年前,好声音以独特节目形式吸引了很多选手和观众的 观注,旨在"只寻找优质声音": 可声音各有特色时,还得看颜值,当然这也无可厚非.虽然扯得有点远,我想表达的是软件开发的稳定 ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) D2. Optimal Subsequences (Hard Version) 数据结构 贪心
D2. Optimal Subsequences (Hard Version) This is the harder version of the problem. In this version, ...
- Paper | Adaptive Computation Time for Recurrent Neural Networks
目录 1. 网络资源 2. 简介 3. 自适应运算时间 3.1 有限运算时间 3.2 误差梯度 1. 网络资源 这篇文章的写作太随意了,读起来不是很好懂(掺杂了过多的技术细节).因此有作者介绍会更好. ...
- 创意编程,Python开发多功能壁纸自动切换工具!
import ctypes import time import requests import os from threading import Thread from tkinter import ...
- IT兄弟连 Java语法教程 流程控制语句 分支结构语句1
不论哪一种编程语言,都会提供两种基本的流程控制结构:分支结构和循环结构.其中分支结构用于实现根据条件来选择性地执行某段代码,循环结构则用于实现根据循环条件重复执行某段代码.Java同样提供了这两种流程 ...