CUDA学习3 Max pooling (python c++ cuda)

1.Python

CNN4 参数优化中有一个CNN模型,其中的限速步是max pooling。

如下所示,Python中运行一个50*100*24*24的max pooling需要3秒。

import numpy as np
import time

def simple_pool(input, ds=(2, 2)):
    n, m, h, w = input.shape
    d, s = ds
    zh = h / d + h % d
    zw = w / s + w % s
    z = np.zeros((n, m,zh,zw))
    for k in range(n):
        for o in range(m):
            for i in range(zh):
                for j in range(zw):
                    maxd = -10000
                    for u in range(min(d,h-d*i) ):
                        for v in range(min(d,w-d*j)):
                            if input[k,o,d*i+u,d*j+v]>maxd:
                                maxd=input[k,o,d*i+u,d*j+v]
                    z[k, o, i, j] = maxd

    return z

N,M,H,W=[50,100,24,24]
a=np.reshape(range(N*M*H*W),(N,M,H,W))*0.01
start_time= time.time()
out_data=simple_pool(a)
print "Cost:",time.time()-start_time,"s"
print out_data[0,0,0,:10]

"""
Cost: 3.08899998665 s
[ 0.25  0.27  0.29  0.31  0.33  0.35  0.37  0.39  0.41  0.43]
"""

2.C++

采用c++,仅需16~30ms。

#include<iostream>
#include<windows.h>

void MaxPool2d(const float* const bottom_data, const int num, const int channels,
    const int height, const int width, const int pooled_height,float* top_data)
{
    const int w = width;
    const int h = height;
    const int m = channels;
    const int n = num;
    const int d = pooled_height;
    const int zh = h / d + h % d;
    const int zw = w / d + w % d;
    int i,j,k,o,u,v,index,index2=0;
    float s;
    for (k = 0; k < n; ++k)
        for (o = 0; o < m; ++o)
            for (i = 0; i < zh; ++i)
                for (j = 0; j < zw; ++j)
                {
                    index=k*m*h*w+o*h*w+d*i*w+d*j;
                    s=-10000.0;
                    for (u = 0; u < d&&(u+d*i)<h; ++u)
                        for (v = 0; v < d&&(v+d*j)<w; ++v)
                            if (*(bottom_data+index+u*w+v)>s)
                                s=*(bottom_data+index+u*w+v);
                    *(top_data+index2)=s;
                    ++index2;
                }
}

int main()
{
  const int N=50,M=100,H=24,W=24,P=(H+1)/2;
  float mul_min=0.01;
  float *input,*output;
  input=new float [N*M*H*W*sizeof(float)];
  output=new float [N*M*P*P*sizeof(float)];
  for(int i=0;i<N*M*H*W;i++)
    *(input+i)=i*mul_min;

  DWORD start_time=GetTickCount();
  MaxPool2d(input,N,M,H,W,2,output);
  DWORD end_time=GetTickCount();
  std::cout<<"Cost: "<<end_time-start_time<<"ms."<<std::endl;
  for(int i=0;i<10;i++)
    std::cout<<*(output+i)<<std::endl;

  delete []input;
  delete []output;
}

/*
Cost: 16ms.
0.25
0.27
0.29
0.31
0.33
0.35
0.37
0.39
0.41
0.43
*/

3.CUDA

在N=50时为16ms,N=500时为141ms(c++中为218ms),略有提升,应该是计算快了一些,数据交换慢了一些。

#include <windows.h>
#include <iostream>

__global__ void MaxPool2d(float* bottom_data, const int height, const int width,
    const int pooled_height,const int out_height,float* top_data)
{
    int x = blockIdx.x;
    int y = blockIdx.y;
    int i,j,u,v,index;
    int index2=x*gridDim.y*out_height*out_height+y*out_height*out_height;
    float s;
    for (i = 0; i < out_height; ++i)
        for (j = 0; j < out_height; ++j)
        {
            index=x*gridDim.y*height*width+y*height*width+i*pooled_height*width+j*pooled_height;
            s=-10000.0;
            for (u = 0; u < pooled_height&&(u+pooled_height*i)<height; ++u)
                for (v = 0; v < pooled_height&&(v+pooled_height*j)<width; ++v)
                    if (*(bottom_data+index+u*width+v)>s)
                        s=*(bottom_data+index+u*width+v);
            *(top_data+index2)=s;
            ++index2;
        }
}

int main()
{
  const int N=500,M=100,H=24,W=24,D=2;
  const int PH=H / D + H % D;
  int image_size = N*M*H*W*sizeof(float);
  int out_size = N*M*PH*PH*sizeof(float);
  float mul_by=0.01;
  float *input,*output,*dev_output,*dev_input;
  input = new float[image_size];
  output = new float[out_size];
  for (int i = 0; i<N*M*H*W; i++)
      *(input + i) = i*mul_by;

  cudaMalloc((void**)&dev_output, out_size);
  cudaMalloc((void**)&dev_input, image_size);
  cudaMemcpy(dev_input, input, image_size, cudaMemcpyHostToDevice);
  dim3    grid(N, M);
  DWORD start_time=GetTickCount();
  MaxPool2d<<<grid,1>>>(dev_input,H,W,D,PH,dev_output);
  cudaMemcpy(output, dev_output, out_size, cudaMemcpyDeviceToHost);
  DWORD end_time=GetTickCount();
  std::cout<<"Cost: "<<end_time-start_time<<"ms."<<std::endl;
  for (int i = 0; i<10; i++)
      std::cout << *(output + i) << std::endl;

  cudaFree(dev_input);
  cudaFree(dev_output);
  delete[] output;
  delete[] input;
  system("pause");
}

/*
Cost: 141ms.
0.25
0.27
0.29
0.31
0.33
0.35
0.37
0.39
0.41
0.43
*/
时间: 2024-12-18 00:09:57

CUDA学习3 Max pooling (python c++ cuda)的相关文章

CUDA学习和总结1

一. 基本概念 1. CUDA 2007年,NVIDIA推出CUDA(Compute Unified Device Architecture,统一计算设备架构)这个编程模型,目的是为了在应用程序中充分利用CPU和GPU各自的优点,实现CPU/GPU联合执行.这种联合执行的需要已经在最新的集中编程模型(OpenCL,OpenACC,C++ AMP)中体现出来了. 2. 并行编程语言和模型 使用比较广泛的是为可扩展的集群计算设计的消息传递接口(Message Passing Interface,MP

CUDA学习之二:shared_memory使用,矩阵相乘

CUDA中使用shared_memory可以加速运算,在矩阵乘法中是一个体现. 矩阵C = A * B,正常运算时我们运用 C[i,j] = A[i,:] * B[:,j] 可以计算出结果.但是在CPU上完成这个运算我们需要大量的时间,设A[m,n],B[n,k],那么C矩阵为m*k,总体,我们需要做m*n*k次乘法运算,m*(b-1)*k次加法运算,并且是串行执行,总体的复杂度为O(m*n*k) . 矩阵类: 1 class Matrix 2 { 3 public: 4 int cols; /

CUDA学习之一:二维矩阵加法

今天忙活了3个小时,竟然被一个苦恼的CUDA小例程给困住了,本来是参照Rachal zhang大神的CUDA学习笔记来一个模仿,结果却自己给自己糊里糊涂,最后还是弄明白了一些. RZ大神对CUDA关于kernel,memory的介绍还是蛮清楚,看完决定写一个二维数组的加法.如果是C++里的加法,那就简单了,用C[i][j] = A[i][j] +B[i][j]就可以. 1 void CppMatAdd(int A[M][N],int B[M][N],int C[M][N]){ 2 for(int

CUDA学习5 常量内存与事件

当线程束中的所有线程都访问相同的只读数据时,使用常量内存将获得额外的性能提升. 常量内存大小限制为64k. 以下摘自hackairM的博文CUDA学习--内存处理之常量内存(4). 常量内存其实只是全局内存的一种虚拟地址形式,并没有特殊保留的常量内存块.常量内存有两个特性,一个是高速缓存,另一个是它支持将单个值广播到线程束中的每个线程.但要注意的是,对于那些数据不太集中或者数据重用率不高的内存访问,尽量不要使用常量内存. 当常量内存将数据分配或广播到线程束中的每个线程时(注意,实际上硬件会将单次

CUDA学习

因为老师要求,现在开始学习CUDA的相关知识.开始在网上找了很多教程,都在一点一点看,后来同学推荐了一本书,是<GPU高性能编CUDA实战>,觉得挺不错的,书上的实例代码我都有码,对CUDA的理解也越来越深了,打算把这些记下来,以后可以复习,也给后来学习的人一点参考,少走弯路. 来老师实验室三周了,每天就是呆在实验室里学习CUDA,我开始以为是用CUDA做图形图像呢,后来才知道老师让我学CUDA是做信号处理的,这个就比较蛋疼了,苦日子在后头呢.本来九月开学呢,我暑假就过来了,想着人丑还不好好学

CUDA学习,第一个kernel函数及代码讲解

前一篇CUDA学习,我们已经完成了编程环境的配置,现在我们继续深入去了解CUDA编程.本博文分为三个部分,第一部分给出一个代码示例,第二部分对代码进行讲解,第三部分根据这个例子介绍如何部署和发起一个kernel函数. 一.代码示例 二.代码解说 申明一个函数,用于检测CUDA运行中是否出错. kernel函数,blockIdx.x表示block在x方向的索引号,blockDim.x表示block在x方向的维度,threadIdx.x表示thread在x方向的索引号. 这里也许你会问,为什么在x方

CUDA学习笔记一

使用VS2013编译CUDA程序时,可能会遇到以下问题: 1.error MSB3721: "D:\Program Files\NVIDIA GPU Computing\Toolkit\CUDA\v7.0\bin\nvcc.exe" -gencode=arch=compute_52,code=\"sm_52,compute_52\" --use-local-env --cl-version 2013 -ccbin "D:\Program Files\Mic

自然语言处理中CNN模型几种常见的Max Pooling操作

/* 版权声明:可以任意转载,转载时请标明文章原始出处和作者信息 .*/ author: 张俊林 CNN是目前自然语言处理中和RNN并驾齐驱的两种最常见的深度学习模型.图1展示了在NLP任务中使用CNN模型的典型网络结构.一般而言,输入的字或者词用Word Embedding的方式表达,这样本来一维的文本信息输入就转换成了二维的输入结构,假设输入X包含m个字符,而每个字符的Word Embedding的长度为d,那么输入就是m*d的二维向量. 图1 自然语言处理中CNN模型典型网络结构 这里可以

给深度学习入门者的Python快速教程

基础篇 numpy和Matplotlib篇 本篇部分代码的下载地址: https://github.com/frombeijingwithlove/dlcv_for_beginners/tree/master/chap5 5.3 Python的科学计算包 – Numpy numpy(Numerical Python extensions)是一个第三方的Python包,用于科学计算.这个库的前身是1995年就开始开发的一个用于数组运算的库.经过了长时间的发展,基本上成了绝大部分Python科学计算