- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我启动了两个OpenMP任务,这些任务只是打印最初设置为1的共享变量的值。我将启动两个任务之间的变量更改为2。
我希望两个任务都能看到变量的更改后的值,即输出应为2 2
。但是我总是得到1 2
或2 1
,如果变量是firstprivate,这就是我期望的结果。
我还尝试在启动任务之前设置锁定,并在注册任务和更改变量后取消设置锁定。还使两个任务都等待锁定,以确保变量已更改。结果是一样的,我不能同时执行两个任务来查看变量的值(2 2)。我怎么了?使用GCC 7.4.0。 omp_get_num_threads
返回8。
#include <iostream>
#include <omp.h>
int main()
{
omp_lock_t lock;
int i = 1;
omp_init_lock(&lock);
#pragma omp parallel default(shared) shared(i)
{
#pragma omp single
{
omp_set_lock(&lock); // set lock before any tasks are registered
#pragma omp task default(shared) shared(i)
{
omp_set_lock(&lock); // should wait until lock is unset and i is 2?
std::cout << i;
omp_unset_lock(&lock);
}
i = 2;
#pragma omp task default(shared) shared(i)
{
omp_set_lock(&lock);
std::cout << i;
omp_unset_lock(&lock);
}
omp_unset_lock(&lock); // unset lock after i is set to 2
}
}
omp_destroy_lock(&lock);
return 0;
}
i
未存储在共享内存中?如果我将其更改为无法存储在寄存器中的内容,或者将其更改为全局的,甚至只是打印其地址(
std::cout << &i;
),该程序就会按预期工作。可能是不确定的行为或GCC问题?
最佳答案
首先,期望对shared
依赖项的排序只是在询问竞争条件。请不要这样做-这只是一种思想练习,因此您可以了解正在发生的事情。在任何实际代码中,请使用可在具有依赖关系的任务之间强制适当的数据流的依赖关系。
预期行为
预期的事件顺序为:
undeferred task
A task for which execution is not deferred with respect to its generating task region. That is, its generating task region is suspended until execution of the undeferred task is completed.
int main()
{
int i = 1;
#pragma omp parallel
#pragma omp single
{
#pragma omp task depend(in:i)
{
std::cout << 'a' << i;
}
#pragma omp task depend(out:i)
i = 2;
#pragma omp task depend(in:i)
{
std::cout << 'b' << i;
}
#pragma omp task depend(in:i)
{
std::cout << 'c' << i;
}
}
return 0;
}
a1c2b2
或
a1b2c2
。请注意,我之所以说是因为写stdout也不是原子的,所以从理论上讲我不能排除偶发的
abc122
或类似的东西。
i
,它们只是挂起子任务,直到生成任务结束。某种形式的内存屏障/刷新可能会解决该问题,并且您还需要停止编译器针对获取和释放锁重新排序对
i
的访问。实现此目的的最简单方法是使
i
成为原子int:
int main()
{
omp_lock_t lock;
omp_init_lock(&lock);
std::atomic<int> i(1);
#pragma omp parallel shared(i)
#pragma omp single
{
omp_set_lock(&lock);
#pragma omp task shared(i)
{
// enter task, then suspend until i = 2
omp_set_lock(&lock);
std::cout << i;
omp_unset_lock(&lock);
}
i = 2;
#pragma omp task shared(i)
{
// enter task, then suspend until i = 2
omp_set_lock(&lock);
std::cout << i;
omp_unset_lock(&lock);
}
// unset lock after i is set to 2 and child tasks are created
// child tasks are possibly started and suspended at this point
omp_unset_lock(&lock);
}
omp_destroy_lock(&lock);
std::cout << std::endl;
return 0;
}
shared
依赖项的排序只是在询问竞争条件。 另外,您正在创建任务以立即将其挂起,这没有任何意义。
volatile int i
,让我们看一下以下任务的程序集(来自gcc的
-S -fverbose-asm
的输出)(带有
###
的行是我的评论):
#pragma omp task shared(i)
{
// enter task, then suspend until i = 2
omp_set_lock(&lock);
__asm__ volatile("mfence":::"memory");
std::cout << i;
omp_unset_lock(&lock);
}
.LFB2346:
.cfi_startproc
.cfi_personality 0x3,__gxx_personality_v0
.cfi_lsda 0x3,.LLSDA2346
pushq %rbp #
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp #,
.cfi_def_cfa_register 6
subq $32, %rsp #,
### get "omp_data_i", a struct containing _the value of i_ and the lock id
movq %rdi, -24(%rbp) # .omp_data_i, .omp_data_i
### get i, store it on the stack at -4
# lock+volatile.cc:15: #pragma omp task shared(i)
movq -24(%rbp), %rax # .omp_data_i, tmp86
movl 8(%rax), %eax # .omp_data_i_2(D)->i, i.6_3
movl %eax, -4(%rbp) # i.6_3, i
### get the lock id and call omp_set_lock
# lock+volatile.cc:18: omp_set_lock(&lock);
movq -24(%rbp), %rax # .omp_data_i, tmp87
movq (%rax), %rax # .omp_data_i_2(D)->lock, _5
movq %rax, %rdi # _5,
call omp_set_lock #
### our manually written assembly
# lock+volatile.cc:20: __asm__ volatile("mfence":::"memory");
#APP
# 20 "lock+volatile.cc" 1
mfence
# 0 "" 2
### get i from the stack and call cout
# lock+volatile.cc:21: std::cout << i;
#NO_APP
movl -4(%rbp), %eax # i, i.0_9
movl %eax, %esi # i.0_9,
movl $_ZSt4cout, %edi #,
call _ZNSolsEi #
### get the lock and call unset_lock
# lock+volatile.cc:22: omp_unset_lock(&lock);
movq -24(%rbp), %rax # .omp_data_i, tmp88
movq (%rax), %rax # .omp_data_i_2(D)->lock, _11
movq %rax, %rdi # _11,
call omp_unset_lock #
int i
(非 Volatile ),我们来看一下此任务的程序集:
#pragma omp task shared(i)
{
// enter task, then suspend until i = 2
omp_set_lock(&lock);
std::cout << __atomic_load_n(&i, __ATOMIC_RELAXED);
omp_unset_lock(&lock);
}
.LFB2346:
.cfi_startproc
.cfi_personality 0x3,__gxx_personality_v0
.cfi_lsda 0x3,.LLSDA2346
pushq %rbp #
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp #,
.cfi_def_cfa_register 6
subq $16, %rsp #,
### get "omp_data_i", a struct containing _the address of i_ and the lock id
movq %rdi, -8(%rbp) # .omp_data_i, .omp_data_i
### get the lock id and call omp_set_lock
# lock+volatile.cc:18: omp_set_lock(&lock);
movq -8(%rbp), %rax # .omp_data_i, tmp87
movq (%rax), %rax # .omp_data_i_2(D)->lock, _3
movq %rax, %rdi # _3,
call omp_set_lock #
### get i and call cout
# lock+volatile.cc:19: std::cout << __atomic_load_n(&i, __ATOMIC_RELAXED);
movq -8(%rbp), %rax # .omp_data_i, tmp88
movq 8(%rax), %rax # .omp_data_i_2(D)->i, _6
movl (%rax), %eax #* _6, _9
movl %eax, %esi # _10,
movl $_ZSt4cout, %edi #,
call _ZNSolsEi #
### get the lock id and call unset_lock
# lock+volatile.cc:20: omp_unset_lock(&lock);
movq -8(%rbp), %rax # .omp_data_i, tmp89
movq (%rax), %rax # .omp_data_i_2(D)->lock, _12
movq %rax, %rdi # _12,
call omp_unset_lock #
i
之前执行了在寄存器中获取
omp_set_lock
的值的操作。我仅使用原子(即使具有宽松的一致性)也设法将其移动到“预期的”位置,大概是因为这样就无法相对于锁对访问进行重新排序。
关于c++ - OpenMP任务看不到共享变量的更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59016886/
只是想知道是否有可能找出谁从 Windows 共享中读取了文件(最好使用 .NET,但 win32 native 可以)? 我想做的是创建类似 awstats 的东西对于 Windows 共享,这样我
是否可以列出 Intent.ACTION_SEND ?我的意思是我需要知道是否有人通过 action_send 在 Facebook 上分享或在 Twitter 上发推文。 最佳答案 也许你想要一个更
我正在使用 Google Apps 应用程序。实际上,我想在不使用密码的情况下访问另一个 ID。我使用了 OAuth,它运行良好。但我无法分享特定人的日历。我尝试了以下代码。 GoogleOAuthP
我怎样才能只创建模拟器...可能吗?我知道,设备需要分发证书。 最佳答案 您只需将应用程序目录从 iPhone 模拟器复制到另一个实例/操作系统版本,它就应该可以工作。 因此,如果您想分发 3.1.3
我想使用多阶段构建来避免每次构建应用程序时都下载我的 Java 项目所需的所有 Maven 依赖项。 我正在考虑在第一阶段解决 Maven 依赖项,然后在第二阶段构建应用程序,这将需要访问在前一阶段下
我正在寻找保护用户下载内容的初步想法。用户下载充满有趣资源的 zip 文件,这些资源被提取到本地文件系统中以供应用程序使用。我的目标是防止用户通过互联网将下载的资源共享给其他用户(假设他们获得了对文件
我想知道在具有移动和桌面版本的网站上共享身份验证、 session 管理等的最佳方法是什么。我们正在运行 Tomcat,并且更愿意将移动站点和桌面站点的应用程序保持在不同的节点上。 我看过类似的帖子,
我发现了这个单例的实现。我怎样才能创建指向它的指针或共享指针?` 为什么这不起作用?自动测试 = Singleton::Instance(); class Singleton { public: st
我有一个 heroku 项目,我想与其他人分享。作为the instructions describe ,我使用 virtualenv 来管理环境和依赖项。有没有办法在新机器上从 requiremen
Maven 将所有 jar 存储在本地存储库 ~/.m2/repository/ 下。用户多时占用空间大。 那么,是否可以由多个用户共享这个本地存储库,或许在不同的目录结构下? 最佳答案 简单的回答
为什么共享 worker 在重新加载页面时死了?应该是复活了我该如何解决这个问题? 重装前 重新加载后(在example.com上按F5) parent worker var port = new S
我正在开发多个小型应用程序,这些应用程序将共享通用和共享模块和 Assets 。 关于如何创建项目结构的部分在这里回答:https://stackoverflow.com/a/61254557/135
我在 RHEL 上安装了 jenkins (localhost:8080),我能够成功地构建代码 现在,我想设置主/从代理。 我的笔记本电脑将充当“Master Jenkins”,而我同事的笔记本电脑
我有这种方法可以根据我使用的 EXTRA_STREAM 共享文本文件或图片。我有这两个我可以选择 i.putExtra(Intent.EXTRA_STREAM, uri); i.putExtra(In
我正在使用 R 中的一个数据分析项目,我正在使用 R 中的敏感私有(private)数据进行一些逻辑和多级建模。我爱上了 。预订 包,我已经创建了一本关于我们的工作流程和分析管道的相当广泛的书。问题是
我正在构建的应用程序需要在 UITabBarController 框架内为多个 View (及其 subview )显示共享的自定义 UIToolbar。自定义工具栏的内容在所有 View 中都是相同
我有多个应用程序,我想共享相同的 eslint 配置: - project_root/ - app1/ - node_modules/ - eslint.rc
我有多个 Electron 应用程序。一个是主应用程序,其他几个功能应用程序。主应用程序上的按钮很少,这将导致功能应用程序打开。这里的问题是每个应用程序都有一个主进程,该进程导致要利用更多的CPU。是
我正在开发一个 Node.js 后端,它通过 websocket 与一些桌面客户端进行通信,而服务器端的通信是从 Web 前端发起的。一切正常,因为我将 SockJS Connection 实例存储在
我对托管多个网站的服务器上的多个用户帐户使用私有(private) SSH key 和无密码条目。 我为每个用户帐户使用相同的私钥。 (因为我很懒?或者那是“正确”的方式)。 我现在想授权该国不同地区
我是一名优秀的程序员,十分优秀!