CPU和GPU实现julia

主要目的是通过对比,学习研究如何编写CUDA程序。julia的算法还是有一定难度的,但不是重点。由于GPU实现了也是做图像识别程序,所以缺省的就是和OPENCV结合起来。

一、CPU实现(julia_cpu.cpp)

//julia_cpu 采用cpu实现julia变换

#include "stdafx.h"
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;
#define DIM 512
struct cuComplex 
{
    float r;
    float i;
    cuComplex(float a,float b):r(a),i(b){}
    float magnitude2(void){return r*r+i*i;}
    cuComplex operator*(const cuComplex& a)
    {
        return cuComplex(r*a.r-i*a.i,i*a.r+r*a.i);
    }
    cuComplex operator+(const cuComplex& a)
    {
        return cuComplex(r+a.r,i+a.i);
    }
};
int julia(int x,int y)
{
    const float scale = 1.5;
    float jx = scale*(float)(DIM/2 - x)/(DIM/2);
    float jy = scale*(float)(DIM/2 - y)/(DIM/2);
    
    cuComplex c(-0.8,0.156);
    cuComplex a(jx,jy);
    for (int i=0;i<200;i++)
    {
        a=a*a +c;
        if (a.magnitude2()>1000)
        {
            return 0;
        }
    }
    return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{    
    
    Mat src = Mat(DIM,DIM,CV_8UC3);//创建画布
    for (int x=0;x<src.rows;x++)
    {
        for (int y=0;y<src.cols;y++)
        {   
            for (int c=0;c<3;c++)
            {
                src.at<Vec3b>(x,y)[c]=julia(x,y)*255;
            }
            
        }
    }
    imshow("src",src);
    waitKey();
    return 0;
}

这里的实现,主要是说明julia的算法,它本身是一个递归的,而且具有一定计算复杂度的算法。

二、GPU实现

为了能够深刻理解这里的技术,我做了一系列的实验。需要注意的是GPU编译非常慢,不知道有什么办法能够加快这个速度。

此外,比较麻烦的就是矩阵的读入读出,因为现在的资料缺乏,所以很多东西还搞不清楚。

1)CUDA和OPENCV联系起来;(test1.cu)

CUDA主要还是来做数学运算的,它本身和OPENCV没有必然的联系。一般来说,计算本身在CUDA中,而OPENCV编写相关转换,进行结果显示。这里实现的功能就是读入一幅单色图像,所有像素进行反转。

编写代码的话,还是基于现有的模板,进行参数的调整,这样来得最快;基于现有的数据不断地调整,这样也能够控制错误。

注意,CUDA核中,不能用任何OPENCV的函数。目前我只能实现这样的效果,因为多数组如何引入,必须要查更多的资料。

主要就是数组的操作,现在只能做单数组,一旦多维就溢出。

//1)CUDA和OPENCV联系起来;(test1.cu)
#include "stdafx.h"
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <stdio.h>
#include <assert.h>
#include <cuda_runtime.h>
#include <helper_functions.h>
#include <helper_cuda.h>
using namespace std;
using namespace cv;
#define N 250
//test1的kernel
__global__ void test1kernel(int *t)
{
    int x = blockIdx.x;
    int y = blockIdx.y;
    int offset = x+y*gridDim.x; 
    t[offset] =255-t[offset];
 
}
int main(void)
{    
    //step0.数据和内存初始化
    Mat src = imread("opencv-logo.png",0);
    resize(src,src,Size(N,N));
    int *dev_t;
    int t[N*N];
    Mat dst = Mat(N,N,CV_8UC3);
    for (int i=0;i<N*N;i++)
    {
        t[i]  =(int)src.at<char>(i/N,i%N);
    }
    checkCudaErrors(cudaMalloc((void **)&dev_t, sizeof(int)*N*N));
    //step1.由cpu向gpu中导入数据
    checkCudaErrors(cudaMemcpy(dev_t, t,sizeof(int)*N*N, cudaMemcpyHostToDevice));
    //step2.gpu运算
    dim3 grid(N,N);
    test1kernel<<<grid,1>>>(dev_t);
    //step3.由gpu向cpu中传输数据
    checkCudaErrors(cudaMemcpy(t, dev_t,sizeof(int)*N*N, cudaMemcpyDeviceToHost));
    //step4.显示结果
    for (int i=0;i<N;i++)
    {
        for (int j=0;j<N;j++)
        {
             int offset = i*N+j;
             for (int c=0;c<3;c++)
             {
                 dst.at<Vec3b>(i,j)[c] =t[offset];
             }
        }
    }
    //step5,释放资源
    checkCudaErrors(cudaFree(dev_t));
    imshow("dst",dst);
    waitKey();
    return 0;
}

2)CUDA计算斐波那契数,思考CNN的实现;

CUDA是否适合斐波那契,像julia这样的,每一个点都是独立的,它很适合;如果能够分出一些块来,应该也是适合的因此,单个的斐波那契运算不适合,但是做到一个数组中,并且以并行化的想法来运算,还是有一定价值的。

结果报不支持递归,那么在以后运算设计的时候要注意这一点。并行设计从来都不是一个简单的问题,必然有很陡峭的学习曲线,需要分丰富的经验,也有很远大的市场。

但是,CNN的确算的上是一个典型的实现了,它不需要串行的运算,而是在大量的并行的结果之后,选择一个最好的参数,所以CNN可以作为图像领域和CUDA结合的一个典型实现。

3)CUDA实现julia。

在前面的基础上,非常顺利

//3)julia
#include "stdafx.h"
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <stdio.h>
#include <assert.h>
#include <cuda_runtime.h>
#include <helper_functions.h>
#include <helper_cuda.h>
using namespace std;
using namespace cv;
#define N 250
struct cuComplex
{
    float r;
    float i;
    __device__ cuComplex(float a,float b): r(a),i(b){}
    __device__ float magnitude2(void)
    {
        return r*r+i*i;
    }
    __device__ cuComplex operator*(const cuComplex& a)
    {
        return cuComplex(r*a.r - i*a.i,i*a.r + r*a.i);
    }
    __device__ cuComplex operator+(const cuComplex& a)
    {
        return cuComplex(r+a.r,i+a.i);
    }
};
__device__ int julia(int x,int y)
{
    const float scale = 1.5;
    float jx = scale*(float)(N/2 - x)/(N/2);
    float jy = scale*(float)(N/2 - y)/(N/2);
    cuComplex c(-0.8,0.156);
    cuComplex a(jx,jy);
    for (int i=0;i<200;i++)
    {
        a=a*a +c;
        if (a.magnitude2()>1000)
        {
            return 0;
        }
    }
    return 1;
}
__device__ int fblx(int offset)
{
    if (offset ==0 || offset==1)
    {
        return offset;
    }
    else
    {
        return(fblx(offset - 1)+fblx(offset - 2));
    }
}
//test3的kernel
__global__ void juliakernel(int *t)
{
    int x = blockIdx.x;
    int y = blockIdx.y;
    int offset = x+y*gridDim.x;
    int juliaValue = julia(x,y);
    t[offset] =juliaValue*255;
}
int main(void)
{    
    //step0.数据和内存初始化
    int *dev_t;
    int t[N*N];
    Mat dst = Mat(N,N,CV_8UC3);
    for (int i=0;i<N*N;i++)
    {
        t[i]  =0;
    }
    checkCudaErrors(cudaMalloc((void **)&dev_t, sizeof(int)*N*N));
    //step1.由cpu向gpu中导入数据
    checkCudaErrors(cudaMemcpy(dev_t, t,sizeof(int)*N*N, cudaMemcpyHostToDevice));
    //step2.gpu运算
    dim3 grid(N,N);
    juliakernel<<<grid,1>>>(dev_t);
    //step3.由gpu向cpu中传输数据
    checkCudaErrors(cudaMemcpy(t, dev_t,sizeof(int)*N*N, cudaMemcpyDeviceToHost));
    //step4.显示结果
    for (int i=0;i<N;i++)
    {
        for (int j=0;j<N;j++)
        {
             int offset = i*N+j;
             printf("%d is %d",offset,t[offset]);
             for (int c=0;c<3;c++)
             {
                  dst.at<Vec3b>(i,j)[c] =t[offset];
             }
        }
    }
    //step5,释放资源
    checkCudaErrors(cudaFree(dev_t));
    imshow("dst",dst);
    waitKey();
    return 0;
}

三、小结

CUDA编程是一个新的领域,虽然文档中都说不复杂、不复杂的,但是想要大规模应用不可能不复杂。所以先基于现有的例子,将能够跑起来的东西跑起来。然后思考融合,形成自己的东西,这就是生产率。我相信,不需要很多的时间,我就能够使用CUDA的计算功能去接触并解决一些以前无法去做的东西。

祝成功,愿回顾。

来自为知笔记(Wiz)

时间: 2024-10-14 00:44:35

CPU和GPU实现julia的相关文章

iOS构建流畅的交互界面--CPU,GPU资源消耗的原因和解决方案

 CPU资源消耗的原因和解决方案对象创建轻量对象代替重量对象* 不需要响应触摸事件的控件:CALayer显示* 对象不涉及UI操作,则尽量放到后台线程创建* 包含有CALayer的控件只能在主线程创建和操作* 通过Storyboard 创建视图对象时,其资源消耗会比直接通过代码创建对象要大非常多,在性能敏感的界面里,storyboard不是一个好的技术选择* 尽量推迟对象创建的时间,并把对象的创建分散到多个任务中去.* 对象的复用代价比释放,创建新对象要小,这类对象应当尽量放到一个缓存池里复用对

图像重采样(CPU和GPU)

1 前言 之前在写影像融合算法的时候,免不了要实现将多光谱影像重采样到全色大小.当时为了不影响融合算法整体开发进度,其中重采样功能用的是GDAL开源库中的Warp接口实现的. 后来发现GDAL Warp接口实现的多光谱到全色影像的重采样主要存在两个问题:1 与原有平台的已有功能不兼容,产生冲突:2 效率较低.因此,决定重新设计和开发一个这样的功能,方便后期软件系统的维护等. 2 图像重采样 图像处理从形式上来说主要包括两个方面:1 单像素或者邻域像素的处理,比如影像的相加或者滤波运算等:2 图像

CPU和GPU性能对比

计算20000次10000点的fft,分别使用CPU和GPU,得 the running time of cpu is : 2.3696s the running time of gpu is : 0.3425s 相同的参数matlab处理的时间为 1.2865s ,理论上gpu最快,cpu次之,matlab最慢,得到的结果不对 处理的环境是(CPU i7 4790K,gpu GTX1080, matlab 2015a,内存1666MHZ 16G, PCI E M.2 固态硬盘(读1.2GB/s

Theano is a Python library: A CPU and GPU math expression compiler

Welcome¶ Theano is a Python library that allows you to define, optimize, and evaluate mathematical expressions involving multi-dimensional arrays efficiently. Theano features: tight integration with NumPy – Use numpy.ndarray in Theano-compiled functi

CPU和GPU双低效,摩尔定律之后一万倍 ——写于TPU版AlphaGo重出江湖之际

本文来自计算机体系结构专家王逵.他认为,“摩尔定律结束之后,性能提升一万倍”不会是科幻,而是发生在我们眼前的事实. 2008年,<三体2:黑暗森林>里写到: 真的很难,你冬眠后不久,就有六个新一代超级计算机大型研究项目同时开始,其中三个是传统结构的,一个是非冯结构的,另外两个分别是量子和生物分子计算机研究项目.但两年后,这六个项目的首席科学家都对我说,我们要的计算能力根本不可能实现.量子计算机项目是最先中断的,现有的物理理论无法提供足够的支持,研究撞到了智子的墙壁上.紧接着生物分子计算机项目也

CPU和GPU的区别

个人认为CPU和GPU各有自己的适应领域.CPU(Central Processing Unit)计算核心较少,通常是双核.四核.八核,但是拥有大量的共享缓存.预测.乱序执行等优化,可以做逻辑非常复杂的计算任务.这一点就当前的GPU来说,仍然难以做到.会牺牲大量的性能甚至造成大量的能源开销. GPU(Graphice Processing Unit),天生拥有大量的处理单元,但是代价是较少的控制单元,就如同它的名字一样,适合图形图像相关的计算,图形图像中每一个点都是独立的,不相关的,并且需要大量

CPU 和 GPU 的区别

作者:知乎用户链接:https://www.zhihu.com/question/19903344/answer/96081382来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. CPU和GPU之所以大不相同,是由于其设计目标的不同,它们分别针对了两种不同的应用场景.CPU需要很强的通用性来处理各种不同的数据类型,同时又要逻辑判断又会引入大量的分支跳转和中断的处理.这些都使得CPU的内部结构异常复杂.而GPU面对的则是类型高度统一的.相互无依赖的大规模数据和不需要被

CPU与GPU区别大揭秘

http://blog.csdn.net/xiaolang85/article/details/51500340 有网友在网上提问:"为什么现在更多需要用的是 GPU 而不是 CPU,比如挖矿甚至破解密码? "以下是比较准确靠谱的回答: 1.现在更多被需要的依然是CPU,只是GPU在大规模并发计算中体现出其一技之长所以应用范围逐渐变得广泛,并成为近些年的热点话题之一. 为什么二者会有如此的不同呢?首先要从CPU和GPU的区别说起. CPU和GPU之所以大不相同,是由于其设计目标的不同,

OpenCL: Shared memory between CPU and GPU in Android development of Qaulcomm plateform

最近的一个高通平台的项目, 对性能要求很苛刻, 我们采用了 OpenCL 实现了主要的功能, 但是瓶颈出现在从 CPU 向 GPU 内存拷贝的部分. 虽然 OpenCL 的 map API 是为了解决这个问题而设计的, 但是在一些固有的框架内, map 并不能避免所有的内存拷贝. 高通针对 OpenCL 有两个非常有用的扩展, 可以有效的解决这个问题: https://www.khronos.org/registry/cl/extensions/qcom/cl_qcom_ion_host_ptr