C++中的volatile和CUDA应用程序的运算符重载

10
我有一个类A,我重载了它的operator=运算符。然而,现在我需要执行以下操作:
volatile A x;
A y;
x = y;

编译时引发错误

error: no operator "=" matches these operands
       operand types are: volatile A = A
如果我去掉了 volatile,代码可以编译。有没有办法在不删除 "volatile" 的情况下编译它(并保持 volatile 的行为)?
基本上这是一个 CUDA 程序,在程序中 'x' 是共享内存(所有线程都可以访问和修改它的值)。我希望它是 "volatile" 类型以避免编译器优化并重用值而不是访问内存地址。
更多问题:开始时,A 只是一个基本类型,例如整数,volatile 的工作方式符合预期并且不会引起任何问题,现在我希望它是一个自定义类(例如 128 位的整数)。我不确定为什么 C++ 在这种情况下会出问题,而对于原始数据类型则不会。
谢谢。
4个回答

7
假设必须使用 volatile 限定符,您需要在 A 中添加一个 volatile 赋值运算符 (A& A::operator=(const A&) volatile)。 const_cast<A&>(x) = y 会使其编译通过,但从技术上讲会导致未定义的行为,并且肯定会消除 volatile 的保证。

谢谢!它已经编译了。但是很遗憾,它给我相同的非易失性行为。 - w00d
@iKid:你期望 volatile 会有什么行为? - Mike Seymour
我在我的问题中添加了解释。 - w00d
此外,仔细考虑如何实现这个函数 - volatile 意味着在你写入时目标可能被其他人写入,因此请确保设置内存屏障或其他措施。 - M.M

3

“在C++线程中,volatile没有太多用处”这条评论与问题无关,该问题涉及到CUDA特定的内容。在CUDA中,需要使用volatile进行warp同步编码。


1

声明一个复制构造函数

volatile A& operator=(volatile A&) volatile;

对我来说,使用 nvcc 可以工作。请注意,您可能只能通过引用传递非原始类型。否则,每当将非原始类型按值传递给非易失性参数时,您将需要更多的复制构造函数,将易失实例转换为非易失实例。 这实际上归结为建立易失正确性(类似于 const 正确性)。


1

在C++线程中,volatile并没有太多用处(请参见Dave Butenhof在http://www.lambdacs.com/cpt/FAQ.html#Q56中的解释)。它不足以确保您的程序将写出的数据从核心本地缓存刷新到其他程序可以看到共享内存中的更新点,而且现在几乎每个人都使用多核处理器,这是一个严重的问题。我建议您使用适当的线程同步方法,例如boost(如果您的可移植性需要匹配),或者可能是POSIX互斥锁和条件变量,如果失败,则使用更多架构相关的技术,如内存屏障或原子操作,这些操作会隐式地在核之间同步内存。

我知道您希望它快速,但快速而不稳定通常不如慢而可靠,特别是如果您发布的产品只在客户的硬件上不稳定。


特别是考虑到pthread_mutex可以非常轻量级。 - doron
@DeadMG:不是的,这就是为什么我们有像Boost.Thread和C++0x线程支持库这样的可移植封装器。 - Mike Seymour
没错。与boost::thread相比,直接推荐POSIX并不是正确的做法。 - Puppy
谢谢,感觉在这种情况下C++设计得很糟糕。 - w00d
5
“volatile在C++中并没有什么大用处”这种说法跟“const在C++中并没有什么大用处”一样无稽之谈。问题不在于volatile,而在于那些认为volatile是某种破损的、有神奇线程同步作用的原语的程序员。实际上,它并不具备这些特性。 - John Dibling
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接