【发布时间】:2018-10-12 00:19:10
【问题描述】:
我正在制作一个 MT Ray-Tracer 多线程,正如标题所说,它的执行时间是单线程版本的两倍。显然目的是将渲染时间减少一半,但我现在所做的只是发送光线追踪方法运行两次,每个线程一次,基本上执行两次相同的渲染。尽管如此,由于线程可以并行运行,因此执行时间不会显着增加。但是大约是翻倍。
这必须与我的多线程设置有关。我认为这与我将它们创建为可连接的事实有关。因此,我将解释我在做什么,并放上相关代码,看看是否有人可以确认是否是问题所在。
我创建了两个线程并将它们设置为可连接的。创建一个 RayTracer,它分配足够的内存来存储图像像素(这在构造函数中完成)。运行两次迭代循环以发送每个线程的相关信息,例如线程 ID 和 Raytracer 实例的地址。
然后pthread_create调用run_thread,其目的是调用ray_tracer:draw方法完成工作。关于draw方法,我有一个
pthread_exit (NULL);
作为它上面的最后一件事(上面唯一的 MT 东西)。然后再做一个循环来加入线程。最后,我开始在一个小循环中写入文件。最后关闭文件,删除draw方法中用于存储图像的数组相关的指针。
我现在可能不需要使用加入,因为我不是在做一个“真正的”多线程光线追踪器,只是渲染它两次,但是一旦我开始在图像像素之间交替(即 thread0 -> 渲染 pixel0 - thread0 -> 存储 pixel0, thread1 -> 渲染 pixel1 - thread1 -> 存储 pixel1, thread0 -> 渲染 pixel2 - thread0 -> 存储 pixel2, , thread1 -> 渲染 pixel3 - thread1 -> 存储 pixel3 等...)我认为我需要它以便能够在文件上以正确的顺序写入像素。
正确吗?我真的需要在这里使用我的方法(或任何其他方法吗?)。如果我这样做,我怎样才能发送线程并发运行,而不是等待另一个完成?问题是否与加入完全无关?
pthread_t threads [2];
thread_data td_array [2];
pthread_attr_t attr;
void *status;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
TGAManager tgaManager ("z.tga",true);
if (tgaManager.isFileOpen()) {
tgaManager.writeHeadersData (image);
RayTracer rt (image.getHeight() * image.getWidth());
int rc;
for (int i=0; i<2; i++) {
//cout << "main() : creating thread, " << i << endl;
td_array[i].thread_id=i;
td_array[i].rt_ptr = &rt;
td_array[i].img_ptr = ℑ
td_array[i].scene_ptr = &scene;
//cout << "td_array.thread_index: " << td_array[i].thread_id << endl;
rc = pthread_create (&threads[i], NULL, RayTracer::run_thread, &td_array[i]);
}
if (rc) {
cout << "Error:unable to create thread," << rc << endl;
exit(-1);
}
pthread_attr_destroy(&attr);
for (int i=0; i<2; i++ ) {
rc = pthread_join(threads[i], &status);
if (rc) {
cout << "Error:unable to join," << rc << endl;
exit(-1);
}
}
//tgaManager.writeImage (rt,image.getSize());
for (int i=0; i<image.getWidth() * image.getHeight(); i++) {
cout << i << endl;
tgaManager.file_writer.put (rt.b[i]);
tgaManager.file_writer.put (rt.c[i]);
tgaManager.file_writer.put (rt.d[i]);
}
tgaManager.closeFile(1);
rt.deleteImgPtr ();
}
【问题讨论】:
-
记住
std::thread存在。 -
您应该衡量花费的时间太长。它是同步或渲染或预处理(准备)或后处理(加入)。因此,在单线程和多线程版本中测量代码的每个部分的持续时间并进行比较。您发现不一致的部分是您的问题。它可能就像慢速像素访问或锁定争斗或使用顺序非线程 api 一样简单......还要确保你的线程不会渲染相同的像素......我通常会为线程安排整行图像,所以如果你有 N-每个
Nth + i行的核心都转到i-th核心。 -
根据我的经验,使用像素粒度往往会变慢。
-
感谢您的回答。我能够使用像素级粒度实现多线程,现在有了真正的性能提升。尽管如此,当我为每个线程做同样的工作时发生的一个问题,现在仍然在发生(我希望当我改变算法时它会消失)看看这个链接:postimg.cc/image/9apkpgxet。飞机的蓝色应该是平滑的。巧合与否,这只发生在这个测试用例中,有一架飞机。我会把它改成正常的,并用单线程比较颜色值,但如果你知道来源,我想听听
标签: c++ multithreading graphics parallel-processing raytracing