我对x86上的顺序一致的加载操作感兴趣.据我所知,汇编程序列表由编译器生成,它在x86上实现为普通加载,但据我所知,普通加载有保证获得语义,而普通商店保证有释放.顺序一致的存储实现为锁定的xchg,而加载为普通负载.这听起来很奇怪,你能详细解释一下吗?
添加
刚刚在互联网上找到,顺序一致的原子载荷可以作为简单的mov完成,只要存储是用锁定的xchg完成的,但是没有证据也没有文档链接.你知道我在哪里可以读到这个吗?
提前致谢.
我想将数据存储在一个大型数组中,并_mm256_stream_si256()在循环中调用.据我所知,然后需要一个内存栅栏来使这些更改对其他线程可见._mm_sfence()说的描述
对在此指令之前发出的所有存储器到存储器指令执行序列化操作.保证在程序顺序之前的每个商店指令在程序顺序之后的任何商店指令之前全局可见.
但是,我最近的当前线程存储是否也可以在后续加载指令中看到(在其他线程中)?或者我必须打电话_mm_mfence()?(后者似乎很慢)
更新:我之前看过这个问题:我什么时候应该使用_mm_sfence _mm_lfence和_mm_mfence.那里的答案主要集中在何时使用围栏.我的问题更具体,该问题的答案不太可能解决这个问题(目前不这样做).
UPDATE2:在注释/答案之后,让我们将"后续加载"定义为线程中的加载,该线程随后获取当前线程当前持有的锁.
我正在编写一些线程C++ 11代码,而且我不确定何时需要使用内存栅栏或其他东西.所以基本上我正在做的事情:
class Worker
{
std::string arg1;
int arg2;
int arg3;
std::thread thread;
public:
Worker( std::string arg1, int arg2, int arg3 )
{
this->arg1 = arg1;
this->arg2 = arg2;
this->arg3 = arg3;
}
void DoWork()
{
this->thread = std::thread( &Worker::Work, this );
}
private:
Work()
{
// Do stuff with args
}
}
int main()
{
Worker worker( "some data", 1, 2 );
worker.DoWork();
// Wait for it to finish
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我想知道,我需要采取哪些步骤来确保在另一个线程上运行的Work()函数中访问args是安全的.它是否足以在构造函数中编写,然后在单独的函数中创建线程?或者我需要一个内存栅栏,如何制作一个内存栅栏以确保所有3个args都是由主线程写入的,然后由Worker线程读取?
谢谢你的帮助!
下面的代码用于将工作分配给多个线程,唤醒它们,并等待它们完成。在这种情况下,“工作”包括“清理卷”。这个操作到底做什么与这个问题无关——它只是对上下文有帮助。该代码是庞大事务处理系统的一部分。
void bf_tree_cleaner::force_all()
{
for (int i = 0; i < vol_m::MAX_VOLS; i++) {
_requested_volumes[i] = true;
}
// fence here (seq_cst)
wakeup_cleaners();
while (true) {
usleep(10000); // 10 ms
bool remains = false;
for (int vol = 0; vol < vol_m::MAX_VOLS; ++vol) {
// fence here (seq_cst)
if (_requested_volumes[vol]) {
remains = true;
break;
}
}
if (!remains) {
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
布尔数组中的值_requested_volumes[i]表明线程是否i有工作要做。完成后,工作线程将其设置为 false 并返回睡眠状态。
我遇到的问题是编译器生成一个无限循环,其中变量remains始终为 true,即使数组中的所有值都已设置为 false。这只发生在-O3.
我尝试了两种解决方案来解决这个问题:
我知道这不是一个新问题,但在阅读了关于c ++ 11内存栅栏后我感到困惑;
如果我有一个读者线程和一个编写器线程.
我可以使用普通的int吗?
int x = 0; // global
writer reader
x = 1; printf("%d\n", x);
Run Code Online (Sandbox Code Playgroud)
这种行为是不确定的?
我可以在读者线程中获得未定义的值吗?
或者就像使用std::atomic_uint_fast32_t或std::atomic<int>?因此,价值将会到达读者线程 - 最终.
std::atomic<int x = 0; // global
writer reader
x.store(1, std::memory_order_relaxed); printf("%d\n", x.load(std::memory_order_relaxed));
Run Code Online (Sandbox Code Playgroud)
答案取决于我使用的平台吗?(例如x86),所以加载/存储普通int是一条CPU指令?
如果两种行为都相似,那么我是否应该期望两种类型的性能相同?