2010-05-27 123 views
1

这是我的第一个多线程实现,所以它可能是一个初学者的错误。线程处理每个第二行像素的渲染(因此所有渲染都在每个线程内处理)。如果线程分别渲染屏幕的上部分和下部分,问题依然存在。多线程光线跟踪噪声

两个线程都从相同的变量中读取,这是否会导致任何问题?从我所了解的只有写入可能会导致并发问题...

可以调用相同的函数会导致任何并发问题吗?再次,从我的理解,这不应该是一个问题...

两次线程写入同一个变量的唯一时间是保存计算的像素颜色。这存储在一个数组中,但它们从不写入该数组中的相同索引。这会导致问题吗?

Multi-threaded rendered image (防止垃圾邮件阻止我直接发布图片..)

诗篇。我在这两种情况下使用完全相同的实现,唯一的区别是为渲染创建的单个线程与两个线程。

+1

你能发表一些代码吗?没有代码,回答你的问题很可能需要一个水晶球。不幸的是,并发问题通常非常非常微妙...... – 2010-05-27 00:56:06

回答

6

两个线程都从相同的变量中读取,这会导致任何问题吗?从我所了解的只有写作会导致并发问题...

这应该没问题。显然,只要数据在两个线程开始读取之前被初始化并且在两个线程完成之后被销毁。

调用相同的函数会导致任何并发问题吗?再次,从我所了解的这不应该是一个问题...

是的,没有。如果没有代码太难分辨。这个函数做什么?它是否依赖共享状态(例如static变量,全局变量,单例...)?如果是的话,那肯定是个问题。如果没有任何共享状态,那么你没事。

两个线程写入同一个变量的唯一时间是保存计算的像素颜色。这存储在一个数组中,但它们从不写入该数组中的相同索引。这会导致问题吗?

有时候可能。一个什么样的数组?如果sizeof(element) == sizeof(void*)可能是安全的,但C++标准在多线程中是静音的,所以它不会强制你的编译器强制你的硬件使其安全。有可能你的平台在这里咬你(例如64位机器和一个写32位的线程,可能会覆盖相邻的32位值),但这并不罕见。通常你最好使用同步来确保。

您可以通过两种方式解决这个问题:

  • 每个线程构建自己的数据,然后将其汇总,当他们完成。
  • 您可以使用mutex保护共享数据。

在我的答案,缺乏承诺的是什么使多线程编程硬:P

例如,从 Intel® 64 and IA-32 Architectures Software Developer's Manuals,描述了不同的平台如何gaurantee不同级别的原子性:

7.1 .1保证原子操作

Intel486处理器(以及更新的 处理器自)保证 以下基本mem ORY操作将 总是用原子进行:

  • 读取或写入的字节
  • 读取或写入一个16位的边界
  • 阅读上对齐的字或写上32位对齐的双字边界

奔腾处理器(并且由于较新的 处理器)保证按照 附加存储器操作 将总是被原子地进行:

  • 读取或写入的64位边界上对齐四字
  • 16位访问,以适应一个32位数据总线内的非高速缓存存储器位置

P6系列处理器(而且由于新 处理器)保证 以下额外的内存操作 将始终原子进行:

  • 未对齐16,32和64位访问以适应高速缓存行

访问可高速缓冲存储是跨越总线宽度,高速缓存行, 分裂内的高速缓存的存储器 和页边界不保证由英特尔酷睿2双核处理器原子, 英特尔凌动,英特尔酷睿双核,奔腾M, 奔腾4,英特尔至强,P6家庭, 奔腾和英特尔486处理器。所述 英特尔Core 2 Duo,英特尔凌,英特尔 酷睿,奔腾M,奔腾4,英特尔 Xeon和P6系列处理器提供允许 外部存储器子系统使 分裂存取原子 总线控制信号;但是, 未对齐的数据访问将会严重影响 处理器的性能,因此应避免使用 。

1

我已经解决了这个问题,我通过为每个线程分别建立数据,就像Stephen提出的那样(不是void * size的元素)。感谢您提供非常详细的答案!

+0

非常好,很高兴你能解决问题! – Stephen 2010-05-31 13:12:34