▶ 使用函数 clEnqueueNativeKernel 来调用 C/C++ 本地函数(在 OpenCL 中将其看做回调函数),使用本地编译器(而不是 OpenCL 编译器)来编译和执行内核

● 代码,似乎很难找到有关 native kernal 的例子,感谢 stack exchange(https://stackoverflow.com/questions/18409256/how-do-you-read-arguments-passed-to-a-native-kernel,https://stackoverflow.com/questions/10140494/using-clenqueuenativekernel-in-opencl)

 #include <stdio.h>
#include <stdlib.h>
#include <cl.h> #pragma warning(disable : 4996) const int rowA = , colA = , colB = ; struct parameter // 传给native kernel 的参数列表
{
unsigned int row_A;
unsigned int col_A;
unsigned int col_B;
float *input_A;
float *input_B;
float *output_C;
}; void multiplyNaive(void *in)
{
struct parameter *para = (struct parameter *)in;// 传入参数只有 para->col_B 错误(呈现随机数),与内存对齐有关?
float sum; // 因为用不了 para->col_B,代码中使用的全局变量代替 para 中的成员
for (i = ; i < rowA; i++)
{
for (j = ; j < colB; j++)
{
for (k = , sum = 0.0f; k < colA; k++)
sum += para->input_A[i * colA + k] * para->input_B[k * colB + j];
para->output_C[i * colB + j] = sum;
}
}
return;
} int main()
{
int i, j, k, correct;
float *A, *B, *C, tempSum;
cl_int status; A = (float*)malloc(sizeof(float) * rowA * colA);
B = (float*)malloc(sizeof(float) * colA * colB);
C = (float*)malloc(sizeof(float) * rowA * colB);
for (i = ; i < rowA * colA; A[i] = , i++);
for (i = ; i < colA * colB; B[i] = , i++); cl_uint nPlatform;
clGetPlatformIDs(, NULL, &nPlatform);
cl_platform_id *listPlatform = (cl_platform_id*)malloc(nPlatform * sizeof(cl_platform_id));
clGetPlatformIDs(nPlatform, listPlatform, NULL);
cl_uint nDevice = ;
clGetDeviceIDs(listPlatform[], CL_DEVICE_TYPE_CPU, , NULL, &nDevice);// 使用支持 NativeKernel 的 intel OpenCL
cl_device_id *listDevice = (cl_device_id*)malloc(nDevice * sizeof(cl_device_id));
clGetDeviceIDs(listPlatform[], CL_DEVICE_TYPE_CPU, nDevice, listDevice, NULL);
cl_context context = clCreateContext(NULL, nDevice, listDevice, NULL, NULL, &status);
cl_command_queue queue = clCreateCommandQueue(context, listDevice[], , &status); cl_mem bufferA = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(float) * rowA * colA, A, &status);
cl_mem bufferB = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(float) * colA * colB, B, &status);
cl_mem bufferC = clCreateBuffer(context, CL_MEM_WRITE_ONLY, sizeof(float) * rowA * colB, NULL, &status); // 设置内核参数
cl_mem bufferList[] = { bufferA, bufferB, bufferC };
// 结构体写法
struct parameter para;
para.row_A = rowA;
para.col_A = colA;
para.col_B = colB;
para.input_A = NULL;
para.input_B = NULL;
para.output_C = NULL;
const void *bufferLocation[] = { &para.input_A, &para.input_B, &para.output_C };
// 列表写法
//void *para[6] = { (void *)rowA, (void *)colA, (void *)colB, NULL, NULL, NULL }; // 参数列表,空出缓冲区的位置
//const void *bufferLocation[3] = { &para[3], &para[4], &para[5] }; // 指明参数列表中哪些位置应该是缓冲区 status = clEnqueueNativeKernel(queue, (void(__stdcall *)(void*))multiplyNaive, (void*)&para, , , bufferList, &bufferLocation[], , NULL, NULL);
// 注意第 7 个参数 &bufferLocation[0],需要的是一个 const void**,而不是 void*[3],不能直接传入 bufferLocation // 返回并检查结果
clEnqueueReadBuffer(queue, bufferC, CL_TRUE, , sizeof(float) * rowA * colB, C, , NULL, NULL);
for (i = , correct = ; i < rowA && correct; i++)
{
for (j = ; j < colB && correct; j++)
{
for (k = , tempSum = 0.0f; k < colA; tempSum += A[i * colA + k] * B[k * colB + j], k++);
if (tempSum != C[i * colB + j])
{
printf("Error at [%d, %d], calculation: %f, reference: %f\n", i, j, C[i*colA + j], tempSum);
correct = ;
}
}
}
if (correct)
printf("Result correct.\n"); // 释放资源
free(A);
free(B);
free(C);
free(listPlatform);
free(listDevice);
clReleaseContext(context);
clReleaseMemObject(bufferA);
clReleaseMemObject(bufferB);
clReleaseMemObject(bufferC);
clReleaseCommandQueue(queue);
getchar();
return ;
}

● 输出结果,我的电脑不支持运行本地函数

-
Error at[, ], calculation: 0.000000, reference : 64.000000

● 输出结果,办公室的电脑,正确计算,但代码中注释的问题没有解决

Result correct.

● 检查设备是否支持 native kernel

 #include <stdio.h>
#include <stdlib.h>
#include <cl.h> int main()
{
unsigned long long val; cl_uint nPlatform;
clGetPlatformIDs(, NULL, &nPlatform);
cl_platform_id *listPlatform = (cl_platform_id*)malloc(nPlatform * sizeof(cl_platform_id));
clGetPlatformIDs(nPlatform, listPlatform, NULL);
cl_uint nDevice = ;
clGetDeviceIDs(listPlatform[], CL_DEVICE_TYPE_ALL, , NULL, &nDevice);
cl_device_id *listDevice = (cl_device_id*)malloc(nDevice * sizeof(cl_device_id));
clGetDeviceIDs(listPlatform[], CL_DEVICE_TYPE_ALL, nDevice, listDevice, NULL); if (clGetDeviceInfo(listDevice[], CL_DEVICE_EXECUTION_CAPABILITIES, sizeof(val), &val, NULL) == CL_SUCCESS)// 获取设备信息 CL_DEVICE_EXECUTION_CAPABILITIES
{
printf("\nEXECUTION_CAPABILITIES: ");
if (val & CL_EXEC_KERNEL)
{
val &= ~CL_EXEC_KERNEL;
printf("Kernel ");
}
if (val & CL_EXEC_NATIVE_KERNEL)
{
val &= ~CL_EXEC_NATIVE_KERNEL;
printf("Native ");
}
if (val)
printf("Unknown (0x%llx) ", val);
printf("\n");
}
free(listPlatform);
free(listDevice);
getchar();
return ;
}

● 输出结果,我的电脑仅支持设备执行,而不支持本地执行

EXECUTION_CAPABILITIES: Kernel

● 用到的函数和定义

 // cl.h
// 设备是否支持函数 clEnqueueNativeKernel 执行回调函数的值
#define CL_EXEC_KERNEL (1 << 0)
#define CL_EXEC_NATIVE_KERNEL (1 << 1) extern CL_API_ENTRY cl_int CL_API_CALL clEnqueueNativeKernel(
cl_command_queue, // 命令队列
void (CL_CALLBACK * /*user_func*/)(void *), // 回调函数
void *, // 参数列表
size_t, // 参数总个数
cl_uint, // 数据对象(包括 bufer 和 image)个数
const cl_mem *, // 数据对象列表
const void **, // 数据对象在参数列表中的地址
cl_uint, // 等待列表中的事件数
const cl_event *, // 等待列表
cl_event * // 本事件标记
) CL_API_SUFFIX__VERSION_1_0;

OpenCL NativeKernel 计算矩阵乘法的更多相关文章

  1. 使用shared memory 计算矩阵乘法 (其实并没有加速多少)

    #include "cuda_runtime.h" #include "device_launch_parameters.h" #include "d ...

  2. 向MapReduce转换:通过部分成绩计算矩阵乘法

    代码共分为四部分: <strong><span style="font-size:18px;">/*** * @author YangXin * @info ...

  3. 蓝桥杯 BASIC_17 矩阵乘法 (矩阵快速幂)

    问题描述 给定一个N阶矩阵A,输出A的M次幂(M是非负整数) 例如: A = 1 2 3 4 A的2次幂 7 10 15 22 输入格式 第一行是一个正整数N.M(1<=N<=30, 0& ...

  4. 有关CUBLAS中的矩阵乘法函数

    关于cuBLAS库中矩阵乘法相关的函数及其输入输出进行详细讨论. ▶ 涨姿势: ● cuBLAS中能用于运算矩阵乘法的函数有4个,分别是 cublasSgemm(单精度实数).cublasDgemm( ...

  5. OpenCL 矩阵乘法

    ▶ 矩阵乘法,按照书里的内容进行了几方面的优化,包括局部内存,矢量数据类型,寄存器,流水线等. ● 最直接的乘法.调用时 main.c 中使用 size_t globalSize[] = { rowA ...

  6. 矩阵乘法的运算量计算(华为OJ)

    题目地址: https://www.nowcoder.com/practice/15e41630514445719a942e004edc0a5b?tpId=37&&tqId=21293 ...

  7. CUDA 矩阵乘法终极优化指南

    作者:马骏 | 旷视 MegEngine 架构师 前言 单精度矩阵乘法(SGEMM)几乎是每一位学习 CUDA 的同学绕不开的案例,这个经典的计算密集型案例可以很好地展示 GPU 编程中常用的优化技巧 ...

  8. *HDU2254 矩阵乘法

    奥运 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submissi ...

  9. *HDU 1757 矩阵乘法

    A Simple Math Problem Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

随机推荐

  1. SQL Server 跨服务器 不同数据库之间复制表的数据

    不同数据库之间复制表的数据的方法: 当表目标表存在时: insert into 目的数据库..表 select * from 源数据库..表 当目标表不存在时: select * into 目的数据库 ...

  2. uva10689矩阵快速幂

    #include<map> #include<set> #include<cmath> #include<queue> #include<stac ...

  3. 棋盘分割(二维区间DP)

    题目大意:给一个棋盘,棋盘上每个格子中都有一个值,现在需要将棋盘切成n个矩形,总共切n-1刀,求最小的均方差.均方差定义为:,其中. 题目分析:将均方差化简得到:均方差2=(Σxi2)/n-平均值2. ...

  4. HQL查询语句中的模糊查询

    From Person this Where this.name like '%abc%' @SuppressWarnings("unchecked") @Override pub ...

  5. 108. Convert Sorted Array to Binary Search Tree 109. Convert Sorted List to Binary Search Tree -- 将有序数组或有序链表转成平衡二叉排序树

    108. Convert Sorted Array to Binary Search Tree Given an array where elements are sorted in ascendin ...

  6. HDU 1241 Oil Deposits bfs 难度:0

    http://acm.hdu.edu.cn/showproblem.php?pid=1241 对每个还未访问的点bfs,到达的点都标为一块,最后统计有多少块即可 #include <cstdio ...

  7. html和js实现滚动条效果

    HTML部分 <!-- 遮罩层 --> <div id="zzc" style="z-index:-1;height:100%;width: 100%; ...

  8. java的初始化(编程思想)

    6.成员初始化 java尽量保证:所有变量在使用前都能得到恰当的初始化.对于方法的局部变量,java以编译错误的形式来贯彻这种保证. 如果类的成员变量时基本类型,那么没有初始化给默认值 在类里定义一个 ...

  9. Internet Explorer 11.0.9600.16428 For Windows 7

    官方消息http://blogs.msdn.com/b/ie/archive/2013/11/07/ie11-for-windows-7-globally-available-for-consumer ...

  10. git一键提交修改文件

    git一键提交修改文件 首先安装git, 有git bash: 新建一个gitcmt文件,放置于与你的项目同级的目录里: 使用:打开git bash, 方法1. git pull\git status ...