优化实验 Optimize( 二 )


  • 多线程共享进程数据,共享简单 。
  • 嵌入式汇编
    1. 原理:通过汇编语言更接近底层,通过对底层直接操作,防止编译器编译出一些冗繁的操作,省去一些不必要的判断
    2. 实现方案:利用嵌入汇编的方法,人为的对底层进行优化
  • 减少除法等一些计算量大的运算的使用
    1. 用移位代替乘除法 。
    2. 能用乘法就不用除法:
      //test1while(a > b / c)// 1.1while(a * c > b)// 1.2//test2 取模运算a = a % b//2.1while(a >= b) //2.2{ a -= b;}
  • GPU编程
    1. 原理:利用GPU多核的特点 , 拥有更强的算力 , 可以更快的完成任务
    2. 实现方案:利用GPU运行程序
  • 多进程优化
    1. 使用LinuxC语言fork函数
    2. 一个进程,包括代码、数据和分配给进程的资源 。fork ( )函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事 , 但如果初始参数或者传入的变量不同 , 两个进程也可以做不同的事 。
      一个进程调用 fork( )函数后,系统先给新的进程分配资源,例如存储数据和代码的空间 。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同 。相当于克隆了一个自己 。
    3. fork函数参考链接:fork函数
  • 优化实验实验任务? 一个图像处理程序实现图像的平滑,其图像分辨率为1920*1080,每一点颜色值为64b,用long img [1920] [1080]存储屏幕上的所有点颜色值,颜色值可从0依行列递增,或真实图像 。
    平滑算法为:任一点的颜色值为其上下左右4个点颜色的平均值,即:
    ?img[i] [j] =(img [i-1] [j] +img[i+1] [j]+img[i] [j-1] +img[i] [j+1] ) / 4 。
    请面向你的CPU与cache,利用本课程学过的优化技术,编写程序 , 并说明你所采用的优化方法 。
    前言关于本次的平滑算法: 不考虑四周 , 不考虑前后变量改变带来的正确性问题 , 只作为优化的任务 。
    但如果考虑其正确性,用一个 dst [1920]] [1080] 存储平滑后的图像值也是可以的 。
    测量性能使用C语言 time.h 库, 获取运行前后时间钟,算出运行时间 。
    void Test(void (*function)()){ clock_t t1 = clock(); int t = 100; while(t--) {function(); } clock_t t2 = clock(); printf("COST %ldms\n",(t2 - t1) * 1000 / CLOCKS_PER_SEC);}原始版本先要写为可优化的版本,所以先枚举列再枚举行 。
    int i, j;for(j = 1; j < WIDTH - 1; j ++ ){ for(i = 1; i < HEIGHT - 1; i ++ ) {img[i][j] = (img[i - 1][j] + img[i + 1][j] + img[i][j + 1] + img[i][j - 1]) / 4; }}面向cache优化改为先枚举行,再枚举列 。
    int i, j;for(i = 1; i < HEIGHT - 1; i ++ ){ for(j = 1; j < WIDTH - 1; j ++ ) {img[i][j] = (img[i - 1][j] + img[i + 1][j] + img[i][j + 1] + img[i][j - 1]) / 4; }}循环展开减少迭代次数 。但是实验结果是性能并没有优化(相比较上一个) 。
    原因应该是:前后变量有运算依赖关系 。
    int block = 4;int i, j;for(i = 1; i < HEIGHT - 1; i ++ ){ for(j = 1; j < WIDTH - 4; j += block) {img[i][j] = (img[i - 1][j] + img[i + 1][j] + img[i][j + 1] + img[i][j - 1]) / 4;img[i][j + 1] = (img[i - 1][j + 1] + img[i + 1][j + 1] + img[i][j + 1 + 1] + img[i][j - 1 + 1]) / 4;img[i][j + 2] = (img[i - 1][j + 2] + img[i + 1][j + 2] + img[i][j + 1 + 2] + img[i][j - 1 + 2]) / 4;img[i][j + 3] = (img[i - 1][j + 3] + img[i + 1][j + 3] + img[i][j + 1 + 3] + img[i][j - 1 + 3]) / 4; } for(;j < WIDTH - 1; j ++ ) {img[i][j] = (img[i - 1][j] + img[i + 1][j] + img[i][j + 1] + img[i][j - 1]) / 4; }}并发优化既然前后变量有运算依赖关系,那我们就不让有依赖关系,并保持循环展开的形式 。
    但实验结果是:没有优化多少,这个原因仍没搞懂 , 或许需要查看汇编代码 。
    int i, j;//为什么是14:14|1918for(i = 1; i < HEIGHT - 1; i ++ ){ for(j = 1; j < WIDTH - 1; j += 14) {img[i][j + 0] = (img[i - 1][j] + img[i + 1][j] + img[i][j + 1] + img[i][j - 1]) / 4;img[i][j + 2] = (img[i - 1][j + 2] + img[i + 1][j + 2] + img[i][j + 1 + 2] + img[i][j - 1 + 2]) / 4;img[i][j + 4] = (img[i - 1][j + 4] + img[i + 1][j + 4] + img[i][j + 1 + 4] + img[i][j - 1 + 4]) / 4;img[i][j + 6] = (img[i - 1][j + 6] + img[i + 1][j + 6] + img[i][j + 1 + 6] + img[i][j - 1 + 6]) / 4;img[i][j + 8] = (img[i - 1][j + 8] + img[i + 1][j + 8] + img[i][j + 1 + 8] + img[i][j - 1 + 8]) / 4;img[i][j + 10] = (img[i - 1][j + 10] + img[i + 1][j + 10] + img[i][j + 1 + 10] + img[i][j - 1 + 10]) / 4;img[i][j + 12] = (img[i - 1][j + 12] + img[i + 1][j + 12] + img[i][j + 1 + 12] + img[i][j - 1 + 12]) / 4; } for(j = 2; j < WIDTH - 1; j += 14) {img[i][j + 0] = (img[i - 1][j] + img[i + 1][j] + img[i][j + 1] + img[i][j - 1]) / 4;img[i][j + 2] = (img[i - 1][j + 2] + img[i + 1][j + 2] + img[i][j + 1 + 2] + img[i][j - 1 + 2]) / 4;img[i][j + 4] = (img[i - 1][j + 4] + img[i + 1][j + 4] + img[i][j + 1 + 4] + img[i][j - 1 + 4]) / 4;img[i][j + 6] = (img[i - 1][j + 6] + img[i + 1][j + 6] + img[i][j + 1 + 6] + img[i][j - 1 + 6]) / 4;img[i][j + 8] = (img[i - 1][j + 8] + img[i + 1][j + 8] + img[i][j + 1 + 8] + img[i][j - 1 + 8]) / 4;img[i][j + 10] = (img[i - 1][j + 10] + img[i + 1][j + 10] + img[i][j + 1 + 10] + img[i][j - 1 + 10]) / 4;img[i][j + 12] = (img[i - 1][j + 12] + img[i + 1][j + 12] + img[i][j + 1 + 12] + img[i][j - 1 + 12]) / 4; }}

    推荐阅读