这是世界上第一个将CNN实用化的例子,实现了手写体字母自动识别。在这个CNN模型中,可以看到输入是一张32 x 32的二维图像,经过卷积层(Convolution)、下采样层(Subsampling,也称Pooling)、全连接层(Full Connection,也称Inner Product)后,得到一组概率密度,我们选其中概率最大的元素作为该模型对输入图像的分类结果。所以实现CNN时,只需要实现三种基本算法:卷积、下采样、矩阵乘。除此之外,每层输出都可选择是否经过非线性变换,常用的非线性变换有ReLU和Sigmoid,前者计算较为简单,使用较为广泛。
__attribute__((num_compute_units(4)))
__kernel
void conv(__global float * a, __global float * b, __global float * c, const int M, const int N, const int K)
{
int gx = get_global_id(0);
int gy = get_global_id(1);
float tmp=0.0f;
for(int x = 0; x < K; x ++)
{
for(int y = 0; y < K; y ++)
{
tmp += a[(gx + x) * M + (gy + y)] * b[x * K + y];
}
}
全连接层计算采用矩阵乘实现,kernel函数如下:
__attribute__((num_compute_units(4)))
__kernel
void gemm(__global float * a, __global float * b, __global float * c, const int M, const int N, const int K)
{
int gx = get_global_id(0);
int gy = get_global_id(1);
int sy = get_global_size(1);
int sx = get_global_size(0);
int s = sx * sy;
for(int x = gx; x < M; x += sx)
{
for(int y = gy; y < N; y += sy)
{
float tmp=0.0f;
for(int z = 0; z < K; z++)
{
tmp += a[z * M + x] * b[y * K + z];
}
c[y * M + x] = tmp;
}
}
}
编译kernel函数需要使用Altera SDK for OpenCL,我用的版本是14.0.0.200,申请了两个月的license。编译使用命令行aoc,得到*.aocx文件。
(未完,跟帖中)
作者: BOB_Sun 时间: 2015-7-23 09:40
Open CL编译输出报告中给出了资源占用情况: