OpenMP:深度优先搜索的好策略

2023-12-03

我正在编写一个 C++ 程序,该程序对封闭的骑士之旅。代码是here.

我想使用 OpenMP 并行化它。我的问题是以一种创建足够程度的并行性的方式来做到这一点。现在相关部分我的代码看起来像这样

#pragma omp parallel for reduction(+:count) if (depth==4)
  for (size_t i=0;i<g.neighbours[last].size();i++){
    auto n = g.neighbours[last][i];
    // See if n can be used to extend or complete the tour

The if (depth==4)我试图确保不会创建太多并行任务,但另一方面会创建足够多的并行任务以使所有处理器保持忙碌。环境depth==2不会改变程序的运行时间。

这似乎行不通。对于 3x12 问题,在我的双核处理器上,OpenMP 版本消耗的总 CPU 时间约为 130 秒,而没有 OpenMP 的单线程版本则需要大约 40 秒的 CPU 时间。

我希望得到有关如何更好地使用 OpenMP 的建议或它不适合解决此问题的原因。

更新:感谢@Zulan,我有一个新版本使用具有更快顺序性能和良好并行化的 OpenMP 任务。


首先,让我们快速了解一下您的应用程序在哪里花费了时间,方法是使用perf:

perf record ./knights_tour_omp 3 12
perf report

# Overhead  Command          Shared Object        Symbol                                                                                         
# ........  ...............  ...................  .................................................................................................
#
    53.29%  knights_tour_om  libc-2.19.so         [.] malloc                                                                                       
    23.16%  knights_tour_om  libc-2.19.so         [.] _int_free                                                                                    
    10.31%  knights_tour_om  libc-2.19.so         [.] _int_malloc                                                                                  
     4.78%  knights_tour_om  knights_tour_omp     [.] _Z13continue_tourIZ4mainEUlRKSt6vectorIiSaIiEEE_EmRK5GraphS4_RKS0_IcSaIcEEiiRT_.constprop.119
     2.64%  knights_tour_om  libc-2.19.so         [.] __memmove_ssse3_back                                                                         
     1.48%  knights_tour_om  libc-2.19.so         [.] malloc_consolidate                                                                 

您的应用程序花费所有时间来分配和释放内存。虽然有一些报道称malloc未完全锁定,它似乎也不能很好地并行化。

不需要做太多进一步的调查就能发现这是由复制引起的visited and path每次迭代的向量。幸运的是,DFS 具有很好的属性,您不一定需要这样做,您可以重用状态并恢复它:

visited[n] = 1;
path.emplace_back(n);
count += continue_tour(g, path, visited, depth+1,remain-1, cb);
visited[n] = 0;
path.pop_back();

但是,对于并行循环,您需要为每个线程创建工作副本,因此您需要为这种情况与原始行为创建单独的路径。

这一微小的变化已将串行运行时间从 22 秒缩短至 2.65 秒。此外,如果有 2 个线程,则时间会降至 2.0 秒。有加速,但效果不太好 - 为什么?为了说明这一点,我使用了 4 个线程(在足够大的系统上)。这是记录的应用程序随时间的执行情况score-p,如图所示Vampir.

enter image description here

红色是实际工作,蓝色是隐式屏障,意味着线程处于空闲状态。似乎总是有 3 或 1 个活动线程。原因很简单:棋盘上的大多数位置都有 4 或 2 个邻居,但其中一个已经被访问过,因此该循环迭代会立即完成。因此,实际工作是在循环的 3 次或 1 次迭代中进行。对于 2 个线程来说,这是一个特别糟糕的匹配。使用 3 个线程,运行时间降至 1.7 秒

注意:所有时间均在 E5-2690 @ 2.90 GHz 上使用 gcc 5.3,无 Turbo。没有注意补偿运行时间的差异。

考虑到单个循环会导致该问题的并行性非常差,您可能会想要嵌套并行循环。我鼓励你尝试一下,但我认为效果不会很好。我认为任务在这种情况下工作得很好,因为任务可以产生其他任务。因此,您可以将每个递归步骤作为任务生成,并让 OMP 运行时找出良好的调度。但请确保将其限制在一定范围内depth,这样任务就不会太短。

我想强调使用工具的重要性:在没有性能分析工具的情况下尝试找出性能问题就像在没有调试器的情况下找出错误一样。perf它很容易用于 Linux,并且其基本形式非常易于使用。然而它非常强大(尽管高级用法可能有一些陷阱)。

附加说明:对于 OpenMP,尝试不同的编译器通常是值得的。例如,对于(固定)任务代码,gcc 的扩展不再超过 4 个线程,而 intel 编译器/omp 运行时甚至可以提供高达 24 个线程的加速。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenMP:深度优先搜索的好策略 的相关文章

  • CMake 找不到请求的 Boost 库

    既然我已经浏览了其他人的解决方案几个小时 但找不到适合我的问题的正确答案 我想将我的具体问题带给您 我正在尝试使用 CMake 构建 vsomeip 为此 我之前构建了 boost 1 55 但是 我在 CMake 中收到以下错误 The
  • 单元测试验证失败

    我正在运行我的单元测试PostMyModel路线 然而 在PostMyModel 我用的是线Validate
  • 在 OnModelCreating 期间设置列名称

    Issue 我目前正在尝试通过设置的属性为我的表及其列添加前缀 我正在使用实体框架核心 我已经正确地为表名添加了前缀 但我似乎无法弄清楚列的前缀 我有一种感觉 我需要使用反射 我已经留下了我的 可能很糟糕的 反思尝试 有人有办法在实体中设置
  • C++ 长 switch 语句还是用地图查找?

    在我的 C 应用程序中 我有一些值充当代表其他值的代码 为了翻译代码 我一直在争论使用 switch 语句还是 stl 映射 开关看起来像这样 int code int value switch code case 1 value 10 b
  • 解析 JWT 令牌以仅获取有效负载内容,无需 C# 或 Blazor 中的外部库

    我正在使用 Blazor 编写可以访问 JWT 的客户端应用程序 我想知道一种简单的方法来读取令牌有效负载内容而不添加额外的依赖项 因为我不需要其他信息 也不需要验证令牌 我认为解析有效负载内容应该足够简单 只需将其写入方法即可 JwtTo
  • CSharpRepl emacs 集成?

    我碰巧知道莫诺CSharpRepl http www mono project com CsharpRepl 是否有 emacs csharp 模式使用它在一个窗口中运行 REPL 并像 python 模式一样在另一个窗口中编译 运行 C
  • C# 5 async/await 线程机制感觉不对?

    为什么让调用线程进入异步方法直到内部 等待 一旦调用异步方法就生成一个线程 这不是更干净吗 这样您就可以确定异步方法会立即返回 您不必担心在异步方法的早期阶段没有做任何昂贵的事情 我倾向于知道某个方法是否要在 我的 线程上执行代码 不管是堵
  • 使用并行任务库时“foreach”失败

    以下代码创建正确数量的文件 但每个文件都包含第一个列表的内容 有人能发现我做错了什么吗 private IList
  • 一元 +/- 运算符如何可能导致“-a”或“+a”中的整数提升,“a”是算术数据类型常量/变量?

    这句看似微不足道的台词摘自我的迈克 巴纳汉和布雷迪的 C 书 第 2 8 8 2 节 http publications gbdirect co uk c book chapter2 expressions and arithmetic h
  • 将表(行)与 OpenXML SDK 2.5 保持在一起

    我想在 Word 文档中生成多个表 每行 2 行 但我想将这两行保留在一起 如果可能的话 new KeepNext 第一行不起作用 new KeepNext 第一行的最后一段不起作用 new CantSplit 放在桌子上不起作用 在所有情
  • 访问 ascx 文件中的母版页控件

    我有一个母版页文件 其中包含 2 个面板控件中的 2 个菜单 我还使用控件来检查用户是否登录并获取用户类型 根据我想要显示 隐藏面板的类型 控件本身不在母版页中引用 而是通过 CMS 系统动态引用 我想在用户控件中使用findcontrol
  • 使用查询表达式对 List 进行排序

    我在使用 Linq 订购这样的结构时遇到问题 public class Person public int ID get set public List
  • 根据对象变量搜索对象列表

    我有一个对象列表 这些对象具有三个变量 ID 名称和值 这个列表中可能有很多对象 我需要根据ID或Name找到一个对象 并更改值 例子 class objec public string Name public int UID public
  • 为什么 Cdecl 调用在“标准”P/Invoke 约定中经常不匹配?

    我正在开发一个相当大的代码库 其中 C 功能是从 C P Invoked 的 我们的代码库中有很多调用 例如 C extern C int stdcall InvokedFunction int 使用相应的 C DllImport CPlu
  • Project Euler #8,我不明白我哪里出了问题[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我正在做项目欧拉第八题 https projecteuler net problem 8 其中我得到了这个大得离谱的数字 7316
  • 从浏览器访问本地文件?

    您好 我想从浏览器访问系统的本地文件 由于涉及大量安全检查 是否可以通过某种方式实现这一目标 或使用 ActiveX 或 Java Applet 的任何其他工作环境 请帮帮我 要通过浏览器访问本地文件 您可以使用签名的 Java Apple
  • 选择查询不适用于使用Parameters.AddWithValue 的参数

    C 中的以下查询不起作用 但我看不出问题所在 string Getquery select from user tbl where emp id emp id and birthdate birthdate cmdR Parameters
  • 如何在 winforms 应用程序的主屏幕显示之前显示欢迎屏幕?

    我想在应用程序启动时加载欢迎屏幕 然后用户单击欢迎屏幕上的按钮 然后关闭欢迎屏幕 最后显示主屏幕 static void Main startup method being called Application EnableVisualSt
  • 需要提取字符串中点后的最后一个数字,如“7.8.9.1.5.1.100”

    我需要提取 C 字符串中最后一个点后面的最后一个数字 例如 7 8 9 1 5 1 100 并将其存储在整数中 Added 该字符串也可以是 7 8 9 1 5 1 1 或 7 8 9 1 5 1 0 我还想验证它在最后一个点之前恰好是 7
  • 如何将 SQL“LIKE”与 LINQ to Entities 结合使用?

    我有一个文本框 允许用户指定搜索字符串 包括通配符 例如 Joh Johnson mit ack on 在使用 LINQ to Entities 之前 我有一个存储过程 该存储过程将该字符串作为参数并执行以下操作 SELECT FROM T

随机推荐

  • 如何在没有 CSR 的情况下在 Tomcat 中安装 GoDaddy SSL 证书?

    我们的一位客户购买通配符 SSL 证书 example com 来自 GoDaddy 他只是简单下载 没有提供 CSR 数据 该 zip 文件中有 3 个文件 那些是fce4f111a61ea3f4 crt gd bundle g2 g1
  • 访问从模板类派生的类中的基成员函数[重复]

    这个问题在这里已经有答案了 我正在工作中开发一个库 并且设计了一个复杂的继承 其中包括模板类并从中派生 我的问题是基模板类具有虚拟重载运算符 它接受 2 个参数并返回一些值 在基类中实现了此运算符 并且大多数派生类没有重新实现此运算符 其他
  • React ReduxReducer:“this.props.tasks.map不是函数”错误

    我正在制作一个 React Redux 示例 但是 我遇到了一个问题并收到以下错误 类型错误 this props tasks map 不是函数 了解更多 我尝试了很多事情 但我似乎无法理解为什么这不起作用 我相信这是 allReducer
  • 从堆栈中删除 ViewController

    在我们的应用程序中 我们有一个登录ViewController A 用户登录时 会自动调用请求导航以导航到下一个ViewController B 然而 完成后我们想要删除登录ViewController A从堆栈中 因此用户无法 返回 到登
  • 在 pebble js 文件中包含外部 javascript 库?

    有什么方法可以在我的 pebble 代码中包含外部 JS 库吗 按照惯例 在网页上我会在我的 head 标签中执行此操作 但在 pebble 中 我无法做到这一点 因为我只使用 JS 那么我怎样才能包含 JavaScript 文件的外部库呢
  • require() 不适用于变量 - React Native

    我遇到一个奇怪的问题 如果我直接设置一个变量 其值类似于 const myString someWord 可以 但是如果我从像 const myString someVariable 这样的变量中获取值 则不起作用 并且如果我在条件块上设置
  • 而在Lua中,它是如何处理的呢?

    我在一个中看到了这段代码Lua 风格指南 print x yes and YES or x Context local function test x print x yes and YES or x rather than if x ye
  • 使用 Boost 库生成的 UUID 与 Java 的唯一性

    我组织的一个 Android 应用程序需要在每个用户首 次启动该应用程序时为其分配一个 UUID 版本 4 目前我们使用 Boost 库 1 58 0 用于此目的 我们的 Android 应用程序将使用 JNI 运行以下代码生成 UUIDv
  • vector::erase() 未按预期工作

    for it1 prime begin it1
  • 在 Python 中将 Excel 工作表从一个工作表复制到另一个工作表

    我想做的就是用 Python 将工作表从 Excel 工作簿复制到另一个 Excel 工作簿 我想保留所有格式 彩色单元格 表格等 我有许多 Excel 文件 我想将所有文件中的第一张工作表复制到一个工作簿中 如果对任何单个工作簿进行更改
  • 如何写入资源文件?

    如果可以从源文件中读取 如下所示 string fileContent Resources Users using var reader new StringReader fileContent string line while line
  • 2 个扭曲的 SSL 证书

    我有这个代码 from twisted web server import Site from twisted web static import Data from twisted internet import reactor ssl
  • 在 R 中的变量列表上按组运行线性模型

    我有一个数据框 我需要为每个组 站点 运行 6 个 2 变量线性模型 然后 我需要将结果转换为数据框 线性模型中的第二个变量发生变化 我已经使用了该部分lapply 但我不知道如何按组运行 我已经在 SO 上找到了答案 可以回答我的部分问题
  • Tkinter 透明度遇到问题

    我在 TKinter 中使顶级小部件淡入时遇到问题 由于某种原因 小部件根本不会淡入 然后它将显示在任务栏中 但只有在单击运行此命令的按钮两次之后 它不应该出现在任务栏中 代码负责这些问题 Alpha 0 0 w1 attributes a
  • 每个序列化程序都支持 OnDeserializedAttribute 吗?

    我只是偶然发现MSDN 上的 OnDeserializedAttribute 描述指出 当应用于方法时 指定在对象图中的对象反序列化后立即调用该方法 相对于图中其他对象的反序列化顺序是不确定的 问题 是否需要具有此属性的方法any序列化器
  • 将额外参数传递给 usort 回调[重复]

    这个问题在这里已经有答案了 我有以下功能 WordPress 可以运行 但这实际上是一个 PHP 问题 他们对我的 term对象根据artist lastname每个对象的元数据中的属性 我想将一个字符串传递到 meta在第一个函数中 这将
  • Twig - 动态数组键

    目前正在开发一个基于 Symfony 的工具 我正在迭代一系列配置设置 我想要实现的目标似乎很简单 我正在努力获得一定的价值 但其中一个键必须是动态的 下面是一个没有动态密钥的工作示例 set id tmod config content
  • 什么是“访问器功能”?

    In 第 4 3 26 节标准 ECMA 262 版本的 根据属性的形式 可以表示值 直接作为数据值 原始值 对象或 函数对象 或间接通过一对访问器函数 我不明白 访问器函数 是什么意思 也没有在规范中找到访问器函数的定义 然后我在网上搜索
  • 如何在 Python 中使用 Selenium 编辑 CodeMirror?

    每次尝试将文本插入网页上的 CodeMirror 时 我都会收到以下错误消息 有谁知道如何使用selenium成功编辑codemirror WebDriverException Message unknown error Cannot re
  • OpenMP:深度优先搜索的好策略

    我正在编写一个 C 程序 该程序对封闭的骑士之旅 代码是here 我想使用 OpenMP 并行化它 我的问题是以一种创建足够程度的并行性的方式来做到这一点 现在相关部分我的代码看起来像这样 pragma omp parallel for r