我是靠谱客的博主 自觉电灯胆,最近开发中收集的这篇文章主要介绍Games101,作业7(多线程提速)多线程多线程处理提速方式线程代码分隔、启动线程提速效果,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

多线程

多线程的相关信息可根据我的另一个blog查看。

多线程处理提速方式

将像素width*height分隔为多份,每一份交给一个线程处理。

分隔方式有:

  • 网格分隔(代码中使用了这种分隔方式)
  • 条形分隔(每一列 或 每一行 为一个线程,更利于编程)

线程代码

  • 输入为线程需要操作的像素区间。x∈[min_x,max_x],y∈[min_y,max_y]
  • 对于网状分隔方式,m横线移动时,数值是连续的,故只需要在纵向移动时初始化m的值。
  • std::lock_guard<std::mutex> lock(mutex_ins);锁管理器

锁管理器:
多个线程访问外部同一个变量并对该变量进行修改时,可能会因为混乱的修改代码的先后顺序导致修改的变量不符合预期。这时候需要锁管理器,使得每一个线程中的修改代码执行完毕后再去执行其他线程的内容。

对于该线程框架:

  • framebuffer[m]为每一个像素的值,而每一个线程有独立计算的像素,相互之间互不影响,故不需要考虑代码运行的先后顺序。
  • process为外部变量,是每一个线程都要修改的公共变量,因为其修改代码只有一句++process(在汇编中只是一条指令,process++也只是两条指令),因此不使用锁管理器可能也不会造成数据混乱。(建议使用锁管理器)
  • UpdateProgress((float)process / scene.height / y_block);为更新进程函数,因为进程信息的显示不能混乱,如果混乱就会…看下面的图。
auto castRayMultiThread = [&](int min_x,int min_y,int max_x,int max_y) {
        for (uint32_t j = min_y; j < max_y; ++j) {
            int m = j  *scene.width + min_x;
            for (uint32_t i = min_x; i < max_x; ++i) {
                // generate primary ray direction
                float x = (2 * (i + 0.5) / (float)scene.width - 1) *
                    imageAspectRatio * scale;
                float y = (1 - 2 * (j + 0.5) / (float)scene.height) * scale;
    
                Vector3f dir = normalize(Vector3f(-x, y, 1));
                for (int k = 0; k < spp; k++) {
                    framebuffer[m] += scene.castRay(Ray(eye_pos, dir), 0) / spp;
                }
                m++;
                
            }
            {
                std::lock_guard<std::mutex> lock(mutex_ins);
                ++process;
                UpdateProgress((float)process / scene.height / y_block);
            }
            
        }
    };

在这里插入图片描述

分隔、启动线程

要确保分隔的线程中像素点不会有重叠,且不会遗漏像素点或越界。

	//分块为5*5个处理单元
    const int x_block = 5;
    const int y_block = 5;
    std::thread th[x_block * y_block];
    //步距计算,步距多加1,保证无论像素有多少,所有像素都可被包含在块中
    int strideX = scene.width / x_block + 1;
    int strideY = scene.height / y_block + 1;

	线程lamada表达式

	// 分块计算光线追踪 
    int id = 0;
    for (int i = 0; i < y_block; i++){//height
        for (int j = 0; j < x_block; j++){//width
            th[id] = std::thread(castRayMultiThread, j* strideX, i* strideY, std::min((j+1)* strideY, scene.width), std::min((i+1) * strideY, scene.height));
            id++;
        }
    }
    for (int i = 0; i < x_block * y_block; i++) th[i].join();
    UpdateProgress(1.f);

提速效果

spp16-----由先前的6分钟提速为30秒左右。

最后

以上就是自觉电灯胆为你收集整理的Games101,作业7(多线程提速)多线程多线程处理提速方式线程代码分隔、启动线程提速效果的全部内容,希望文章能够帮你解决Games101,作业7(多线程提速)多线程多线程处理提速方式线程代码分隔、启动线程提速效果所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部