• 一步一步写一个简单通用的makefile(三)


    上一篇一步一步写一个简单通用的makefile(二) 里面的makefile 实现对通用的代码进行编译,这一章我将会对上一次的makefile 进行进一步的优化.

    优化后的makefile:

    #Hellomake
    #Magnum, 2014-10-20
    # 指令编译器和选项
    CC=gcc
    CFLAGS=-Wall
    # 需要链接库的库名,比如libm.a,就是-lm,需要去掉前面的lib和后面的.a
    LIBS=-lm
    # 设置默认搜索头文件的路径,优先是这个,然后是系统路径
    IncludeDir = -I./include/
    # 需要链接的库的路径
    LinkDir = #-L
    OBJ_DIR = ./obj
    BIN_DIR = ./bin
    
    #PROJECT_TOP_DIR  设置成pwd 或者"./"都行
    PROJECT_TOP_DIR=$(shell pwd)#$(shell cd ../; pwd)
    PROJECT_BIN_DIR=$(PROJECT_TOP_DIR)/bin
    PROJECT_SRC_DIR=$(PROJECT_TOP_DIR)/src
    PROJECT_LIB_DIR=$(PROJECT_TOP_DIR)/lib
    PROJECT_OBJ_DIR=$(PROJECT_TOP_DIR)/objs
    MKDIR := mkdir -p
    
    # 目标文件
    EXE_NAME=hellomake
    TARGET=$(BIN_DIR)/$(EXE_NAME)
    
    #源文件的文件类型
    FILE_TYPE=c
    src=$(wildcard $(PROJECT_SRC_DIR)/*.$(FILE_TYPE))
    dir= $(notdir $(src))
    PROJECT_OBJ= $(patsubst %.$(FILE_TYPE),%.o,$(dir) )
    PROJECT_ALL_OBJS= $(addprefix $(PROJECT_OBJ_DIR)/, $(PROJECT_OBJ))
    
    all: chdir $(TARGET)
        @echo "magnum $(PROJECT_OBJ)"
        @echo "magnum $(PROJECT_OBJ_DIR)"
        @echo "magnum $(PROJECT_ALL_OBJS)"
    
    $(TARGET): $(PROJECT_ALL_OBJS)
        $(CC) -o $@ $^ $(LinkDir) $(LIBS) 
    
    chdir:
        @if test ! -d $(PROJECT_OBJ_DIR) ; 
            then 
            mkdir $(PROJECT_OBJ_DIR) ; 
        fi
    
        @if test ! -d $(PROJECT_BIN_DIR) ; 
            then 
            mkdir $(PROJECT_BIN_DIR) ; 
        fi
    
    .PHONY : clean
    clean:
        -rm -rf $(PROJECT_BIN_DIR) $(PROJECT_OBJ_DIR) 
    
    $(PROJECT_OBJ_DIR)/%.o:$(PROJECT_SRC_DIR)/%.$(FILE_TYPE)
        $(CC) $(CFLAGS) -o $@ -c $< $(IncludeDir)

    这个优化后的makefile 对于一般需要写一个小的测试程序都有一定的通用性,如果需要对新的程序进行修改:
    1. 编译类型C用gcc, c++用g++

    2. 源文件的路径 PROJECT_SRC_DIR

    3. 文件类型c 还是cpp

    4. 还有这三个:

    # 需要链接库的库名,比如libm.a,就是-lm,需要去掉前面的lib和后面的.a
    LIBS=-lm
    # 设置默认搜索头文件的路径,优先是这个,然后是系统路径
    IncludeDir = -I./include/
    # 需要链接的库的路径
    LinkDir = #-L

    下面我就用这个模板去编译一个opencl的小程序。

    文件树如下:

    .
    ├── convolve.cl
    ├── convolve_cl.cpp
    ├── makefile
    └── makefile~

    很简单的只有3个文件, convolve.cl, convolve_cl.cpp, makefile.

    convolve_cl.cpp源码:

    // newTutorial1.cpp : Defines the entry point for the console application.
    //
    
    //#include "stdafx.h"
    #include <CL/cl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <iostream>
    #include <fstream>
    #include <string.h>
    #include <string>
    #include <pthread.h>
    using namespace std;
    #pragma comment (lib,"OpenCL.lib")
    
    #define WIDTH 1920
    #define HEIGHT 1080
    #define FRAMES 1
    typedef unsigned char   uint8_t;
    
    static double now_ms(void) {
      struct timespec res;
      clock_gettime(CLOCK_REALTIME, &res);
      return 1000.0 * res.tv_sec + (double) res.tv_nsec / 1e6;
    }
    
    
    static int filter0(uint8_t *src, uint8_t *dst, uint8_t *ocl, int w, int h) {
      printf("filter 0 ,w=%d, h=%d
    ",w, h);
      double start, end;
      int i =1;
      int j =1;
      if(w > WIDTH || h > HEIGHT)
        return 1;
      //start = now_ms();
      for (i = 1; i < h - 1; ++i) {
        for (j = 1; j < w - 1; ++j) {
          int index = j + i * w;
          uint8_t lu = src[index - 1 - w];
          uint8_t lm = src[index - 1];
          uint8_t ld = src[index - 1 + w];
          uint8_t mu = src[index - w];
          uint8_t mm = src[index];
          uint8_t md = src[index + w];
          uint8_t ru = src[index + 1 - w];
          uint8_t rm = src[index + 1];
          uint8_t rd = src[index + 1 + w];
          int sum = lu + lm + ld + mu + mm + md + ru + rm + rd;
         // printf("%d, %d, %d, %d, %d, %d, %d %d, %d,
    ",lu, lm, ld, mu, mm, md, ru, rm, rd);
          dst[index] = (uint8_t)sum / 9 + 1;
         // printf(" dst[%d] =%d",index, dst[index]);
          if(ocl[index] != dst[index])
            printf("index[%d] differ 
    ", index);
        }
      //  printf("
    ");
      }
      end = now_ms();
      //printf("filter 0 %f 
    ", end - start);
      return 0;
    }  
    
    
    //°ÑÎıŸÎÄŒþ¶ÁÈëÒ»žöstringÖÐ
    int convertToString(const char *filename, std::string& s)
    {
        size_t size;
        char*  str;
    
        std::fstream f(filename, (std::fstream::in | std::fstream::binary));
    
        if(f.is_open())
        {
            size_t fileSize;
            f.seekg(0, std::fstream::end);
            size = fileSize = (size_t)f.tellg();
            f.seekg(0, std::fstream::beg);
    
            str = new char[size+1];
            if(!str)
            {
                f.close();
                return NULL;
            }
    
            f.read(str, fileSize);
            f.close();
            str[size] = '';
    
            s = str;
            delete[] str;
            return 0;
        }
        printf("Error: Failed to open file %s
    ", filename);
        return 1;
    }
    
    int main(int argc, char* argv[])
    {
      int i, ret;
      double start, end;
      uint8_t * inputBuf;
      uint8_t * dstBuf1;
      uint8_t * dstBuf2;
      inputBuf =(uint8_t *)malloc(WIDTH * HEIGHT * sizeof(uint8_t));
      dstBuf1 =(uint8_t *)malloc(WIDTH * HEIGHT * sizeof(uint8_t));
      dstBuf2 =(uint8_t *)malloc(WIDTH * HEIGHT * sizeof(uint8_t));
      memset(dstBuf1,0,WIDTH * HEIGHT * sizeof(uint8_t));
      memset(dstBuf2,0,WIDTH * HEIGHT * sizeof(uint8_t));
    
      srand( (unsigned)time( NULL ) ); 
      for(i = 0; i < WIDTH * HEIGHT; i++) {
          inputBuf[i] = rand()%255;
        //printf("[%d] =%d
    ", i, inputBuf[i]);  
      }
      
      //return 0;
        cl_uint status;
        cl_platform_id platform;
    
        //ŽŽœšÆœÌš¶ÔÏó
        status = clGetPlatformIDs( 1, &platform, NULL );
    
        cl_device_id device;
    
        //ŽŽœšGPUÉ豞
        clGetDeviceIDs( platform, CL_DEVICE_TYPE_GPU,
            1,
            &device,
            NULL);
        cl_uint maxComputeUnits;
        status = clGetDeviceInfo(device,CL_DEVICE_MAX_COMPUTE_UNITS,
          sizeof(cl_uint),
          &maxComputeUnits,
          NULL);
        printf("maxComputeUnits = %d
    " ,maxComputeUnits);
    
    
        //ŽŽœšcontext
        cl_context context = clCreateContext( NULL,
            1,
            &device,
            NULL, NULL, NULL);
        //ŽŽœšÃüÁî¶ÓÁÐ
        cl_command_queue queue = clCreateCommandQueue( context,
            device,
            CL_QUEUE_PROFILING_ENABLE, NULL );
    
        //ŽŽœšÈýžöOpenCLÄÚŽæ¶ÔÏó
        cl_mem clinbuf = clCreateBuffer(context,
            CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
            WIDTH*HEIGHT*sizeof(cl_uchar),inputBuf,
            NULL );
        
        cl_mem cloutbuf = clCreateBuffer( context,
            CL_MEM_WRITE_ONLY,
            WIDTH*HEIGHT * sizeof(cl_uchar),
            NULL, NULL );
    
        const char * filename  = "convolve.cl";
        std::string  sourceStr;
        status = convertToString(filename, sourceStr);
        const char * source    = sourceStr.c_str();
        size_t sourceSize[]    = { strlen(source) };
    
        //ŽŽœš³ÌÐò¶ÔÏó
        cl_program program = clCreateProgramWithSource(
            context, 
            1, 
            &source,
            sourceSize,
            NULL);
        //±àÒë³ÌÐò¶ÔÏó
        status = clBuildProgram( program, 1, &device, NULL, NULL, NULL );
        if(status != 0)
        {
            printf("clBuild failed:%d
    ", status);
            char tbuf[0x10000];
            clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0x10000, tbuf, NULL);
            printf("
    %s
    ", tbuf);
            return -1;
        }
    
        cl_int dimx = WIDTH;
        cl_int dimy = HEIGHT;
        cl_event ev;
        cl_kernel kernel;
        cl_ulong startTime, endTime;
        cl_ulong kernelExecTimeNs;
        float *op_data = 0;
        
    #if 1
        //ŽŽœšKernel¶ÔÏó
         kernel = clCreateKernel( program, "filter", NULL );
    
        //ÉèÖÃKernel²ÎÊý
        
        clSetKernelArg(kernel, 0, sizeof(cl_mem),  (void *)&clinbuf); 
           clSetKernelArg(kernel, 1, sizeof(cl_int),  (void *)&dimx);
        clSetKernelArg(kernel, 2, sizeof(cl_int),  (void *)&dimy);
        clSetKernelArg(kernel, 3, sizeof(cl_mem),  (void *)&cloutbuf);
    
    
        //Set local and global workgroup sizes
        size_t localws[2] = {1, 1} ; 
        size_t globalws[2] = {WIDTH,HEIGHT};
    
       
        //ÖŽÐÐkernel
        clEnqueueNDRangeKernel( 
            queue ,kernel, 
            2, 0, globalws, NULL, 
            0, NULL, &ev);
    
        clFinish( queue );
     //ŒÆËãkerenlÖŽÐÐʱŒä 
        
        clGetEventProfilingInfo(ev, CL_PROFILING_COMMAND_START,
            sizeof(cl_ulong), &startTime, NULL);
        clGetEventProfilingInfo(ev, CL_PROFILING_COMMAND_END,
            sizeof(cl_ulong), &endTime, NULL);
        kernelExecTimeNs = endTime-startTime;
        printf("kernal exec time :%8.6f ms
     ", kernelExecTimeNs*1e-6 );
    
        //ÊýŸÝ¿œ»ØhostÄÚŽæ
        cl_uchar *ptr;
        ptr = (cl_uchar *) clEnqueueMapBuffer( queue,
            cloutbuf,
            CL_TRUE,
            CL_MAP_READ,
            0,
            WIDTH*HEIGHT * sizeof(cl_uchar),
            0, NULL, NULL, NULL );
       //œá¹ûÑéÖ€£¬ºÍcpuŒÆËãµÄœá¹û±ÈœÏ
    
        start = now_ms();
        for(i = 0; i< FRAMES; i++) {
          ret = filter0(inputBuf, dstBuf1, ptr,WIDTH, HEIGHT);
          if(ret)
            printf("filter Fail 
    ");
        }
        end = now_ms();
        printf("filter 0 %f 
    ", (end - start)/FRAMES);
    
        //ÑéÖ€GPUŒÆËãœá¹û
    /*    for(i = 0; i < M*N; i++)
        {
            //printf("%d, %6.3f,%6.3f
    ",i,outbuf[i],op_data[i]);
            if(abs(dstBuf1[i] - dstBuf2[i]) > 0.0001)
            {
                printf("check failed
    ");
                break;
            }
        }    
        if(i == M*N)
            printf("check passed
    ");   */
      #endif
    
        if(inputBuf)
            free(inputBuf);
        if(dstBuf1)
            free(dstBuf1);
        if(dstBuf2)
            free(dstBuf2);
    
    
        //ÉŸ³ýOpenCL×ÊÔŽ¶ÔÏó
        clReleaseMemObject(clinbuf); 
        clReleaseMemObject(cloutbuf);
        clReleaseProgram(program);
        clReleaseCommandQueue(queue);
        clReleaseContext(context);
        return 0;
    }
    View Code

    convolve.cl 源码:

    #pragma OPENCL EXTENSION cl_amd_printf : enable
    
    
    __kernel void filter( __global uchar* in, int Width, int Height, __global uchar* out)
    {
        // WIDTH
        int row = get_global_id(0);    
        //HEIGHT
        int col   = get_global_id(1);   
    //    int wi = get_global_size(0);
    //    int he = get_global_size(1);
       // printf("Magnum Global w= %d, h= %d,row=%d, col =%d
    ",wi,he,row,col);
        if(row == 0 || col == 0 ||row == Width -1 || col == Height -1)
          return;
        
        int index = row + col * Width;
        uchar lu = in[index - 1 - Width];
        uchar lm = in[index - 1];
        uchar ld = in[index - 1 + Width];
        uchar mu = in[index - Width];
        uchar mm = in[index];
        uchar md = in[index + Width];
        uchar ru = in[index + 1 - Width];
        uchar rm = in[index + 1];
        uchar rd = in[index + 1 + Width];
        int sum = lu + lm + ld + mu + mm + md + ru + rm + rd;
        out[index] = (uchar)sum / 9 + 1;
       // printf("%d, %d, %d, %d, %d, %d, %d %d, %d,
    ",lu, lm, ld, mu, mm, md, ru, rm, rd);
      //  printf("dst[%d] = %d
    ", index, out[index]);
    }

    下面是修改上面给出的模板makefile文件,来编译这个程序:
    1. 因为是cpp,所以CC=g++, FILE_TYPE=cpp
    2. 可执行文件的名字:EXE_NAME=convolve_cl

    3. 链接的库:

    LIBS= -lOpenCL -lfreeimage -lrt
    IncludeDir = -I/opt/AMDAPP/include
    LinkDir = -L/opt/AMDAPP/lib/x86_64
    修改后的makefile如下:

    #Hellomake
    #Magnum, 2014-10-19
    # 指令编译器和选项
    CC=g++
    CFLAGS=-Wall
    # 需要链接库的库名,比如libm.a,就是-lm,需要去掉前面的lib和后面的.a
    LIBS= -lOpenCL -lfreeimage -lrt
    # 设置默认搜索头文件的路径,优先是这个,然后是系统路径
    IncludeDir = -I/opt/AMDAPP/include 
    # 需要链接的库的路径
    LinkDir = -L/opt/AMDAPP/lib/x86_64 
    OBJ_DIR = ./obj
    BIN_DIR = ./bin
    
    #PROJECT_TOP_DIR  设置成pwd 或者"./"都行
    PROJECT_TOP_DIR=.#$(shell pwd)#$(shell cd ../; pwd)
    PROJECT_BIN_DIR=$(PROJECT_TOP_DIR)/bin
    PROJECT_SRC_DIR=$(PROJECT_TOP_DIR)/
    PROJECT_LIB_DIR=$(PROJECT_TOP_DIR)/lib
    PROJECT_OBJ_DIR=$(PROJECT_TOP_DIR)/objs
    MKDIR := mkdir -p
    
    # 目标文件
    EXE_NAME=convolve_cl
    TARGET=$(BIN_DIR)/$(EXE_NAME)
    
    #源文件的文件类型
    FILE_TYPE=cpp
    src=$(wildcard $(PROJECT_SRC_DIR)/*.$(FILE_TYPE))
    dir= $(notdir $(src))
    PROJECT_OBJ= $(patsubst %.$(FILE_TYPE),%.o,$(dir) )
    PROJECT_ALL_OBJS= $(addprefix $(PROJECT_OBJ_DIR)/, $(PROJECT_OBJ))
    
    all: chdir $(TARGET)
        @echo "magnum $(PROJECT_OBJ)"
        @echo "magnum $(PROJECT_OBJ_DIR)"
        @echo "magnum $(PROJECT_ALL_OBJS)"
    
    $(TARGET): $(PROJECT_ALL_OBJS)
        $(CC) -o $@ $^ $(LinkDir) $(LIBS) 
    
    chdir:
        @if test ! -d $(PROJECT_OBJ_DIR) ; 
            then 
            mkdir $(PROJECT_OBJ_DIR) ; 
        fi
    
        @if test ! -d $(PROJECT_BIN_DIR) ; 
            then 
            mkdir $(PROJECT_BIN_DIR) ; 
        fi
    
    .PHONY : clean
    clean:
        -rm -rf $(PROJECT_BIN_DIR) $(PROJECT_OBJ_DIR) 
    
    $(PROJECT_OBJ_DIR)/%.o:$(PROJECT_SRC_DIR)/%.$(FILE_TYPE)
        $(CC) $(CFLAGS) -o $@ -c $< $(IncludeDir)

    可以看到相比较之前的makefile只需要修改几个文件即可。
    我的这个是ubuntu 环境 AMD显卡的opencl程序,虽然你们的环境有些不同,但是对于你们需要修改的编译程序也是同样适用的

  • 相关阅读:
    knox 编译 源码
    springboot 新建项目
    python 在工程中处理相对路径的思考
    Mac配置虚拟环境Virtualenv,安装Python科学计算包详解
    Python 日志文件处理
    Django与JS交互的示例代码-django js 获取 python 字典-Django 前后台的数据传递
    python for 循环
    Java Script 学习日志 Div
    如何制作windows live writer绿色便携版
    中国大数据企业排行榜V6.0- 5 年后再去看看中几个大数据公司的发展状况
  • 原文地址:https://www.cnblogs.com/biglucky/p/4037973.html
Copyright © 2020-2023  润新知