矩阵相乘其实就是前一个矩阵的每一行乘以后一个矩阵的每一列,然后将乘后的每一个数字相加,得到结果矩阵的指定位置的数值。具体算法回顾一下线性代数即可。但是这种行列相乘其实都是独立的,如果是CPU计算必须串行算法,一行一列的乘,但是放到GPU里面则可以并行相乘,如果维数很大那就会大大节约时间。

具体代码如下:

__kernel
void simpleMultiply(__global float* outPutC,
int widthA,
int heightA,
int widthB ,
int heightB ,
__global float* inputA ,
__global float* inputB
)
{
int row = get_global_id();
int col = get_global_id();
float sum = 0.0f ;
for(int i=;i<widthA; i++)
{
sum += inputA[row*widthA+i] * inputB[i*widthB+col];
}
outPutC[row*widthB+col] = sum;
} ;
// FirstOpenCL.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include<time.h>
#include <string>
#include<math.h>
#include <vector>
#include <CL/cl.h>
#include <fstream> using namespace std; #pragma comment (lib,"OpenCL.lib")
std::string convertToString(const char *filename)
{
size_t size;
char* str;
std::string s;
std::fstream f(filename, (std::fstream::in | std::fstream::binary));
if(f.is_open())
{
size_t fileSize;
f.seekg(, std::fstream::end);
size = fileSize = (size_t)f.tellg();
f.seekg(, std::fstream::beg);
str = new char[size+];
if(!str)
{
f.close();
std::cout << "Memory allocation failed";
return NULL;
} f.read(str, fileSize);
f.close();
str[size] = '\0';
s = str;
delete[] str;
return s;
}
else
{
std::cout << "\nFile containg the kernel code(\".cl\") not found. Please copy the required file in the folder containg the executable.\n";
exit();
}
return NULL;
} int main()
{
//查询平台
cl_int ciErrNum;
cl_platform_id platform;
ciErrNum = clGetPlatformIDs(, &platform, NULL); //获取设备信息
cl_device_id device;
cl_int status;
cl_uint maxDims;
cl_event events[];
size_t globalThreads[];
size_t localThreads[];
size_t maxWorkGroupSize;
size_t maxWorkItemSizes[]; ciErrNum = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, , &device, NULL);
status = clGetDeviceInfo( device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(size_t),(void*)&maxWorkGroupSize,NULL);
status = clGetDeviceInfo( device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(cl_uint),(void*)&maxDims, NULL);
status = clGetDeviceInfo( device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(size_t)*maxDims,(void*)maxWorkItemSizes, NULL); //创建上下文
cl_context ctx = clCreateContext(NULL, , &device, NULL, NULL, &ciErrNum);
cl_command_queue myqueue = clCreateCommandQueue(ctx,device,,&ciErrNum); int wA=,hA=;
int wB=,hB=;
int wC=,hC=; // 数组的大小
const int elementsA = wA*hA;
const int elementsB = wB*hB;
const int elementsC = hA*wB; // 计算内存大小
size_t datasizeA = sizeof(float)*elementsA;
size_t datasizeB = sizeof(float)*elementsB;
size_t datasizeC = sizeof(float)*elementsC;
// 分配内存空间
float *A = (float*)malloc(datasizeA);
float *B = (float*)malloc(datasizeB);
float *C = (float*)malloc(datasizeC); // 初始化输入数组
for(int i = ;i < elementsA;i++)
{
A[i] = (float)((float)i + 1.0);
}
for(int i = ;i < elementsB;i++)
{
B[i] = (float)((float)i + 1.0);
} cl_mem bufferA = clCreateBuffer(ctx,CL_MEM_READ_ONLY,wA*hA*sizeof(float),NULL,&ciErrNum);
ciErrNum = clEnqueueWriteBuffer(myqueue,bufferA,CL_TRUE,,wA*hA*sizeof(float),(void*)A,,NULL,NULL); cl_mem bufferB = clCreateBuffer(ctx,CL_MEM_READ_ONLY,wB*hB*sizeof(float),NULL,&ciErrNum);
ciErrNum = clEnqueueWriteBuffer(myqueue,bufferB,CL_TRUE,,wB*hB*sizeof(float),(void*)B,,NULL,NULL); cl_mem bufferC = clCreateBuffer(ctx,CL_MEM_WRITE_ONLY,hA*wB*sizeof(float),NULL,&ciErrNum); //运行时kernel编译
const char * filename = "HelloWorld_Kernel.cl";
std::string sourceStr = convertToString(filename);
const char * source = sourceStr.c_str();
size_t sourceSize[] = { strlen(source) };
//直接将CL文件读到记忆体
cl_program myprog = clCreateProgramWithSource( ctx, ,&source, sourceSize, &ciErrNum);
//cl_program myprog = clCreateProgramWithSource(ctx,1,(const char**)&programSource,NULL,&ciErrNum);
ciErrNum = clBuildProgram(myprog,,NULL,NULL,NULL,NULL); cl_kernel mykernel = clCreateKernel(myprog,"simpleMultiply",&ciErrNum);
//运行程序
clSetKernelArg(mykernel,,sizeof(cl_mem),(void*)&bufferC);
clSetKernelArg(mykernel,,sizeof(cl_mem),(void*)&wA);
clSetKernelArg(mykernel,,sizeof(cl_mem),(void*)&hA);
clSetKernelArg(mykernel,,sizeof(cl_mem),(void*)&wB);
clSetKernelArg(mykernel,,sizeof(cl_mem),(void*)&hB);
clSetKernelArg(mykernel,,sizeof(cl_mem),(void*)&bufferA);
clSetKernelArg(mykernel,,sizeof(cl_mem),(void*)&bufferB); size_t localws[] ={wC,wC};
size_t globalws[]={wC,hC}; ciErrNum = clEnqueueNDRangeKernel(myqueue,mykernel,,NULL,globalws,localws,,NULL,&events[]);
status = clWaitForEvents(, &events[]);
status = clReleaseEvent(events[]);
//将结果拷贝到主机端
ciErrNum = clEnqueueReadBuffer(myqueue,bufferC,CL_TRUE,,wC*hC*sizeof(float),(void*)C,,NULL,&events[]); status = clWaitForEvents(, &events[]);
status = clReleaseEvent(events[]); printf("\nArray A:\n");
for (int i = ; i < wA; i++) {
for (int j = ; j < hA; j++)
printf("%4.3f\t", A[i*hA + j]);
printf("\n");
}
printf("\nArray B:\n");
for (int i = ; i < wB; i++) {
for (int j = ; j < hB; j++)
printf("%4.3f\t", B[i*hB + j]);
printf("\n");
}
printf("\nArray C:\n");
for (int i = ; i < wC; i++) {
for (int j = ; j < hC; j++)
printf("%4.3f\t", C[i*hC + j]);
printf("\n");
} getchar();
return ;
}

【转载】OpenCL实现矩阵相乘的更多相关文章

  1. CUDA编程-(2)其实写个矩阵相乘并不是那么难

    程序代码及图解析: #include <iostream> #include "book.h" __global__ void add( int a, int b, i ...

  2. Strassen 矩阵相乘算法(转)

    偶尔在算法课本上面看到矩阵相乘的算法,联想到自己曾经在蓝桥杯系统上曾经做过一道矩阵相乘的题目,当时用的是普通的矩阵相乘的方法,效率极低,勉强通过编译.所以决定研究一下Strassen矩阵相乘算法,由于 ...

  3. python版 mapreduce 矩阵相乘

    参考张老师的mapreduce 矩阵相乘. 转载请注明:来自chybot的学习笔记http://i.cnblogs.com/EditPosts.aspx?postid=4541939 下面是我用pyt ...

  4. Opencv中Mat矩阵相乘——点乘、dot、mul运算详解

    Opencv中Mat矩阵相乘——点乘.dot.mul运算详解 2016年09月02日 00:00:36 -牧野- 阅读数:59593 标签: Opencv矩阵相乘点乘dotmul 更多 个人分类: O ...

  5. POJ 1651:Multiplication Puzzle 矩阵相乘式DP

    Multiplication Puzzle Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7118   Accepted:  ...

  6. HDU1575Tr A(矩阵相乘与快速幂)

    Tr A hdu1575 就是一个快速幂的应用: 只要知道怎么求矩阵相乘!!(比赛就知道会超时,就是没想到快速幂!!!) #include<iostream> #include<st ...

  7. <矩阵的基本操作:矩阵相加,矩阵相乘,矩阵转置>

    //矩阵的基本操作:矩阵相加,矩阵相乘,矩阵转置 #include<stdio.h> #include<stdlib.h> #define M 2 #define N 3 #d ...

  8. 利用Hadoop实现超大矩阵相乘之我见(二)

    前文 在<利用Hadoop实现超大矩阵相乘之我见(一)>中我们所介绍的方法有着“计算过程中文件占用存储空间大”这个缺陷,本文中我们着重解决这个问题. 矩阵相乘计算思想 传统的矩阵相乘方法为 ...

  9. 利用Hadoop实现超大矩阵相乘之我见(一)

    前记 最近,公司一位挺优秀的总务离职,欢送宴上,她对我说“你是一位挺优秀的程序员”,刚说完,立马道歉说“对不起,我说你是程序员是不是侮辱你了?”我挺诧异,程序员现在是很低端,很被人瞧不起的工作吗?或许 ...

随机推荐

  1. Linux下Qt调用共享库文件.so

    修改已有的pro文件,添加如下几句: INCLUDEPATH += /home/ubuntu/camera/camera/LIBS += -L/home/ubuntu/camera/camera -l ...

  2. Eureka注册中心是什么?

    Eureka注册中心是什么? Eureka注册中心是什么? Eureka是Netflix开发的服务发现组件,本身是一个基于REST的服务.Spring Cloud将它集成在其子项目spring-clo ...

  3. github合并分支到master

    (1)切换到master分支 git checkout master (2) 将backup分支的代合并到master git merge backup (3) 查看状态 git status (4) ...

  4. Promise 解决同步请求问题

    在写小程序和vue项目中,由于 api 不提供 同步请求,因此,可以通过  Promise 来实现 同步请求操作 在这里 对于 Promise 不太了解的小伙伴 可以查找 Promise 的api 文 ...

  5. Excel如何快速渲染百万级别的数据

    Excel主要经历1.查询2.渲染的方式 关于查询: 不同技术水平的人有不同的解决方案,目前我采用的是 1:多线程查询 2:一个异步后台线程每次查询100条便渲染,采用的“懒加载方式”,这样可以做到实 ...

  6. java中的访问修饰符详解

    主要讲述一下java中protected的修饰控制范围. 在叙述protected修饰符使用之前,先来说一下java,可以发现,开发java程序是一个时时刻刻都在编写类.开发类.定义类的过程.类里面可 ...

  7. 使用vue-cli脚手架和vue-router搭建项目(一)

    之前做的项目一直比较简单,并没有引入整个路由库.今天准备练习下

  8. fedora23上安装和运行MySQL server (MySQL 已经被MariaDB取代)

    [root@localhost kemin]# dnf install mysql-server Fedora 23 - x86_64 - Updates                        ...

  9. Keystone controller.py & routers.py代码解析

    目录 目录 Keystone WSGI 实现 controllerspy routerspy 参考文档 Keystone WSGI 实现 Keystone 项目把每个功能都分到单独的目录下,EXAMP ...

  10. 分享一套高级Java笔试题(实拍高清图)

    分享一套高级Java笔试题 微信群里群友分享的 刚好他在笔试 有些问题不会发到群里求助 如果你最近正好在面试 需要参考需要提升 这套试题或许对你有用 下面是部分分享原图 下面是微信群中群友的热议 非常 ...