矩阵相乘其实就是前一个矩阵的每一行乘以后一个矩阵的每一列,然后将乘后的每一个数字相加,得到结果矩阵的指定位置的数值。具体算法回顾一下线性代数即可。但是这种行列相乘其实都是独立的,如果是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. jmeter-测试webservice接口

    测试webservice接口(soap类型接口) 一.webservice协议的本质 一个经过封装的post类型的HTTP请求 Web service一般就是用SOAP协议通过HTTP来调用它,其实他 ...

  2. 判断字符串是否为JSON

    function isJSON(str) { if (typeof str == 'string') { try { var obj=JSON.parse(str); if(typeof obj == ...

  3. Nginx负载均衡与转发

    1.6种负载均衡策略 1.轮询 :默认方式 2.weight : 权重方式 3.ip_hash :依据ip分配方式 4.least_conn :最少连接方式 5.fair(第三方) :响应时间方式 6 ...

  4. ARM 异常处理过程,指令[ swi ]

    1.  发生异常: 程序正常执行,突然被一个不正常的事件打断正在执行的程序,执行相应的异常事件对应的程序 2.  5 种异常模式对应着 7 种异常源:   异常工作模式      异常源 FIR   ...

  5. Linux 进程间通信 无名管道(pipe)

    无名管道: 1)只能用于具有亲缘关系的进程之间的通信(无名管道是某一个进程创建的,不像普通文件有路径,在文件系统中是不可见的,其他进程要想打开,只能通过继承的方式去打开) 2)半双工的通信模式,具有固 ...

  6. 笔记46 Hibernate快速入门(三)

    Hibernate相关概念 一.事物概念 Hibernate的任何对数据有改动的操作,都应该被放在事务里面. hibernate中的事务由s.beginTransaction();开始由s.getTr ...

  7. h5 app 设置全屏

    h5 app的全屏和沉浸式状态栏是不一样的 全屏模式 常见使用场景:如果页面是全屏游戏,一般会直接让状态栏消失,也就是页面全屏.webview高度全屏了,状态栏没有了.写法: 终端支持:没有终端类型限 ...

  8. 从psd图中将图层导出成单独文件

  9. NX二次开发-设置WCS位置UF_CSYS_set_wcs

    NX9+VS2012 UF_initialize(); //输入X向量Y向量输出一个3*3矩阵 ] = {0.0, 0.0, 1.0}; ] = {0.0, 1.0, 0.0}; ]; UF_MTX3 ...

  10. NX二次开发-UF_MODL_ask_point_containment获取一个点是在体(面,边)的边界内部,外部,还是边界上

    NX9+VS2012 #include <uf.h> #include <uf_modl.h> #include <uf_curve.h> #include < ...