并行框架和避免错误共享

2024-04-27

最近,我回答了一个关于优化可能的并行方法来生成任意基数的每个排列的问题。我发布了类似的答案并行化,实施不佳代码块列表,有人几乎立即指出了这一点:

这几乎肯定会给你带来错误的共享,并且可能会慢很多倍。 (归功于gjvdkamp https://stackoverflow.com/users/65747/gjvdkamp)

他们是对的,那就是death慢的。也就是说,我研究了这个话题,发现了一些有趣的材料和建议 http://download.microsoft.com/download/3/a/7/3a7fa450-1f33-41f7-9e6d-3aa95b5a6aea/MSDNMagazine2008_10en-us.chm(仅存档 MSDN 杂志,.NET 问题:错误共享)来对抗它。如果我理解正确的话,当线程访问连续内存时(也就是说,可能支持该内存的数组)ConcurrentStack),可能会出现虚假共享。


对于水平线下方的代码,aBytes is:

struct Bytes {
  public byte A; public byte B; public byte C; public byte D;
  public byte E; public byte F; public byte G; public byte H;
}

对于我自己的测试,我希望获得此运行的并行版本并且真正更快,因此我根据原始代码创建了一个简单的示例。6 as limits[0]对我来说这是一个懒惰的选择——我的电脑有 6 个核心。

单线程块 平均运行时间:10s0059ms

  var data = new List<Bytes>();
  var limits = new byte[] { 6, 16, 16, 16, 32, 8, 8, 8 };

  for (byte a = 0; a < limits[0]; a++)
  for (byte b = 0; b < limits[1]; b++)
  for (byte c = 0; c < limits[2]; c++)
  for (byte d = 0; d < limits[3]; d++)
  for (byte e = 0; e < limits[4]; e++)
  for (byte f = 0; f < limits[5]; f++)
  for (byte g = 0; g < limits[6]; g++)
  for (byte h = 0; h < limits[7]; h++)
    data.Add(new Bytes {
      A = a, B = b, C = c, D = d, 
      E = e, F = f, G = g, H = h
    });

并行化,实施不佳 平均运行时间:81s729ms,约 8700 次争用

  var data = new ConcurrentStack<Bytes>();
  var limits = new byte[] { 6, 16, 16, 16, 32, 8, 8, 8 };

  Parallel.For(0, limits[0], (a) => {
    for (byte b = 0; b < limits[1]; b++)
    for (byte c = 0; c < limits[2]; c++)
    for (byte d = 0; d < limits[3]; d++)
    for (byte e = 0; e < limits[4]; e++)
    for (byte f = 0; f < limits[5]; f++)
    for (byte g = 0; g < limits[6]; g++)
    for (byte h = 0; h < limits[7]; h++)
      data.Push(new Bytes {
        A = (byte)a,B = b,C = c,D = d,
        E = e,F = f,G = g,H = h
      });
  }); 

并行化,??执行 平均运行时间:5s833ms,92 次争用

  var data = new ConcurrentStack<List<Bytes>>();
  var limits = new byte[] { 6, 16, 16, 16, 32, 8, 8, 8 };

  Parallel.For (0, limits[0], () => new List<Bytes>(), 
    (a, loop, localList) => { 
      for (byte b = 0; b < limits[1]; b++)
      for (byte c = 0; c < limits[2]; c++)
      for (byte d = 0; d < limits[3]; d++)
      for (byte e = 0; e < limits[4]; e++)
      for (byte f = 0; f < limits[5]; f++)
      for (byte g = 0; g < limits[6]; g++)
      for (byte h = 0; h < limits[7]; h++)
        localList.Add(new Bytes {
          A = (byte)a, B = b, C = c, D = d,
          E = e, F = f, G = g, H = h
        });
      return localList;
  }, x => {
    data.Push(x);
  });

我很高兴我得到了一个比单线程版本更快的实现。我预计结果接近 10 秒/6 左右,即 1.6 秒左右,但这可能是一个天真的期望。

我的问题是对于实际上比单线程版本更快的并行实现,是否可以对操作应用进一步的优化?我想知道与并行化相关的优化,而不是用于计算值的算法的改进。具体来说:

  • 我知道存储和填充的优化struct代替byte[],但它与并行化无关(或者是吗?)
  • 我知道所需的值可以使用纹波进位加法器进行延迟计算,但与struct优化。

首先,我最初的假设是Parallel.For() and Parallel.ForEach()错了。

糟糕的并行实现很可能有 6 个线程都试图写入单个线程CouncurrentStack()立刻。使用线程局部变量(下面将详细解释)的良好实现每个任务仅访问共享变量一次,几乎消除了任何争用。

使用时Parallel.For() and Parallel.ForEach(), you cannot只需在线替换for or foreach和他们一起循环。这并不是说它不能是盲目的改进,但如果不检查问题并对其进行检测,使用它们就会在问题上投入多线程,因为它可能会使问题变得更快。

**Parallel.For() and Parallel.ForEach()具有重载,允许您为Task他们最终在每次迭代执行之前和之后创建并运行一个表达式。

如果您有一个并行操作Parallel.For() or Parallel.ForEach(),使用此重载可能是个好主意:

public static ParallelLoopResult For<TLocal>(
    int fromInclusive,
    int toExclusive,
    Func<TLocal> localInit,
    Func<int, ParallelLoopState, TLocal, TLocal> body,
    Action<TLocal> localFinally
)

例如,调用For()将 1 到 100 之间的所有整数相加,

var total = 0;

Parallel.For(0, 101, () => 0,  // <-- localInit
(i, state, localTotal) => { // <-- body
  localTotal += i;
  return localTotal;
}, localTotal => { <-- localFinally
  Interlocked.Add(ref total, localTotal);
});

Console.WriteLine(total);

localInit应该是一个初始化本地状态类型的 lambda,该类型被传递给body and localFinally拉姆达。请注意,我不建议使用并行化来实现 1 到 100 的求和,而只是举一个简单的示例来简化示例。

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

并行框架和避免错误共享 的相关文章

  • 如何在C++中实现模板类协变?

    是否可以以这样一种方式实现类模板 如果模板参数相关 一个对象可以转换为另一个对象 这是一个展示这个想法的例子 当然它不会编译 struct Base struct Derived Base template
  • 嵌入式系统中的malloc [重复]

    这个问题在这里已经有答案了 我正在使用嵌入式系统 该应用程序在 AT91SAMxxxx 和 cortex m3 lpc17xxx 上运行 我正在研究动态内存分配 因为它会极大地改变应用程序的外观 并给我更多的力量 我认为我唯一真正的路线是为
  • 如何在我的应用程序中使用 Windows Key

    Like Windows Key E Opens a new Explorer Window And Windows Key R Displays the Run command 如何在应用程序的 KeyDown 事件中使用 Windows
  • 使用 Google Analytics API 在 C# 中显示信息

    我一整天都在寻找一个好的解决方案 但谷歌发展得太快了 我找不到有效的解决方案 我想做的是 我有一个 Web 应用程序 它有一个管理部分 用户需要登录才能查看信息 在本节中 我想显示来自 GA 的一些数据 例如某些特定网址的综合浏览量 因为我
  • HttpClient 像浏览器一样请求

    当我通过 HttpClient 类调用网站 www livescore com 时 我总是收到错误 500 可能服务器阻止了来自 HttpClient 的请求 1 还有其他方法可以从网页获取html吗 2 如何设置标题来获取html内容 当
  • 基于范围的 for 循环中的未命名循环变量?

    有没有什么方法可以不在基于范围的 for 循环中 使用 循环变量 同时也避免编译器发出有关未使用它的警告 对于上下文 我正在尝试执行以下操作 我启用了 将警告视为错误 并且我不想进行像通过在某处毫无意义地提及变量来强制 使用 变量这样的黑客
  • A* 之间的差异 pA = 新 A;和 A* pA = 新 A();

    在 C 中 以下两个动态对象创建之间的确切区别是什么 A pA new A A pA new A 我做了一些测试 但似乎在这两种情况下 都调用了默认构造函数 并且仅调用了它 我正在寻找性能方面的任何差异 Thanks If A是 POD 类
  • 线程、进程和 Application.Exit()

    我的应用程序由主消息循环 GUI 和线程 Task Factory 组成 在线程中我调用一些第三方应用程序var p new Process 但是当我调用Application Exit 在消息循环中 我可以看到在线程中启动的进程仍在内存中
  • 我的 strlcpy 版本

    海湾合作委员会 4 4 4 c89 我的程序做了很多字符串处理 我不想使用 strncpy 因为它不会终止 我不能使用 strlcpy 因为它不可移植 只是几个问题 我怎样才能让我的函数正常运行 以确保它完全安全稳定 单元测试 这对于生产来
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • AccessViolationException 未处理

    我正在尝试使用史蒂夫 桑德森的博客文章 http blog stevensanderson com 2010 01 28 editing a variable length list aspnet mvc 2 style 为了在我的 ASP
  • char指针或char变量的默认值是什么[重复]

    这个问题在这里已经有答案了 下面是我尝试打印 char 变量和指针的默认值 值的代码 但无法在控制台上看到它 它是否有默认值或只是无法读取 ASCII 范围 include
  • 已过时 - OpenCV 的错误模式

    我正在使用 OpenCV 1 进行一些图像处理 并且对 cvSetErrMode 函数 它是 CxCore 的一部分 感到困惑 OpenCV 具有三种错误模式 叶 调用错误处理程序后 程序终止 Parent 程序没有终止 但错误处理程序被调
  • 如何在内存中存储分子?

    我想将分子存储在内存中 这些可以是简单的分子 Methane CH4 C H bond length 108 7 pm H H angle 109 degrees But also more complex molecules like p
  • GDK3/GTK3窗口更新的精确定时

    我有一个使用 GTK 用 C 语言编写的应用程序 尽管该语言对于这个问题可能并不重要 这个应用程序有全屏gtk window与单个gtk drawing area 对于绘图区域 我已经通过注册了一个刻度回调gtk widget add ti
  • Bing 地图运行时错误 Windows 8.1

    当我运行带有 Bing Map 集成的 Windows 8 1 应用程序时 出现以下错误 Windows UI Xaml Markup XamlParseException 类型的异常 发生在 DistanceApp exe 中 但未在用户
  • 窗体最大化时自动缩放子控件

    有没有办法在最大化屏幕或更改分辨率时使 Windows 窗体上的所有内容自动缩放 我发现手动缩放它是正确的 但是当切换分辨率时我每次都必须更改它 this AutoScaleDimensions new System Drawing Siz
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的
  • C++ 成员函数中的“if (!this)”有多糟糕?

    如果我遇到旧代码if this return 在应用程序中 这种风险有多严重 它是一个危险的定时炸弹 需要立即在应用程序范围内进行搜索和销毁工作 还是更像是一种可以悄悄留在原处的代码气味 我不打算writing当然 执行此操作的代码 相反
  • 如何连接字符串和常量字符?

    我需要将 hello world 放入c中 我怎样才能做到这一点 string a hello const char b world const char C string a hello const char b world a b co

随机推荐

  • 设置快捷方式以替换 VIM 中轻松选择的字符串

    我有很多 php html 文件 其中包含许多应该使用 gettext 国际化的字符串 因此 我必须遍历每个文件 找到 消息 字符串并将每个字符串替换为 I use vim and would like to setup a shortcu
  • 单击 libGDX 中的 Actor

    我的游戏中有一个覆盖层 其中包含屏幕图像和屏幕 上 的一组按钮 截屏 My Screen有一个Stage The Stage有一组Group对象 我将其视为图层 第一组具有背景 中间的组具有游戏元素 最前面的组具有屏幕覆盖 覆盖层由一个Im
  • 如何找出 Kubernetes 中可用的端口?

    我想在 kubernetes 集群中的不同端口上运行多个服务 并且想知道如何检查哪些端口可用并且不会与我的服务产生任何冲突 我还想知道每个端口上的服务名称 以便我可以更好地理解我的配置 有类似的问题涉及验证哪个NodePorts已经在使用中
  • Rails 4 中的“find_all_by_id”相当于什么

    我有一个 id 数组 我想使用活动记录查询从数据库中查找它们各自的记录 例如 ids 2 3 1 现在 对于我来说 要查找 id 是数组中的其中之一的特定模型的所有记录 在较低版本的 Rails 中 我想我可以执行以下操作 Model fi
  • 使用滚动视图通过 Swift 放大图像

    我正在从 Apple 的 Swift 应用程序开发 中学习 Swift 我遇到了约束问题 特别是在第 593 页的 I Spy 实验室 它基本上希望您创建一个滚动视图 其中包含图像视图 并使其可以放大图像并滚动它 例如当您打开照片时 在 照
  • 通过调用 shell 脚本设置 ant 属性?

    有没有办法通过捕获 shellscript 的输出来设置 ant 属性 或另一个蚂蚁任务 像这样的事情
  • 宏扩展忽略了 MSVC 中的一些标记

    我在 msvc 编译器中遇到宏扩展问题 我希望将以下代码扩展为F x 它在 gcc 和 clang 上执行 但 msvc 将其扩展为F忽略x令牌 这里发生了什么 define S s s define F define M S S F x
  • 如何在文本文件中找到最长的 N 行并将其打印到标准输出?

    第一行包含数字 N 的值 后跟多行 我可以按照n 2算法的顺序解决它 有人可以建议一个更好的吗 您可以使用最小堆并在 O n log N 中完成 heap new Min Heap N foreach line in text if len
  • 如何将字节数组转换为任何类型

    好的 我看到有人问如何将字节数组转换为int string Stream等等 答案各不相同 我个人还没有找到任何令人满意的答案 这里有一些我们想要将字节数组转换成的类型 UnityEngine Font可以吸收ttf data UnityE
  • Google Inceptionism:按类别获取图像

    在著名的 Google Inceptionism 文章中 http googleresearch blogspot jp 2015 06 inceptionism going deeper into neural html http goo
  • 将另一个类添加到 div

    我有一个函数可以检查表单提交的年龄 然后根据年龄在 div 中返回新内容 现在我只是使用 getElementById 来替换 HTML 内容 但我认为如果我也可以向 div 添加一个类 那对我来说会更好 例如我有 if under cer
  • SceneKit 绘制曲线

    我想用 SceneKit 画一条贝塞尔曲线 并认为这可行 func drawCurvedLine let scene SCNScene let scnView self view as SCNView scnView scene scene
  • 共享对象发送方法

    在 FMS 中 我想使用共享对象在聊天应用程序中发送消息 因为它是实时的 我的问题是 如何使用共享对象在实时聊天应用程序中向用户来回发送消息 这需要服务器端脚本 客户端还是两者都需要 您只需要在服务器端编写一些特定功能的代码 例如安全功能
  • 如何声明返回函数指针的函数指针

    如何声明一个函数指针 该指针指向具有相同参数的函数 并返回一个指向具有相同参数的函数的指针 i e funcPtr指着func1 int a int b and func1返回指向另一个函数的指针func2 int a int b func
  • 无法获取POST参数

    我正在使用 WebApp2 作为框架在 Python 中开发一个 Web 应用程序 我无法获取通过填写表单提交的http POST请求参数 这是我创建的表单的 HTML 代码
  • 使用 Passport-facebook 的 Facebook OAuth 安全性

    我目前正在使用客户端 React 组件让用户通过我的应用程序中的 OAuth 登录 Facebook 在服务器端 我使用 npm 包护照 Facebook 令牌 https github com drudge passport facebo
  • 无法将“Windows.UI.Xaml.Controls.ItemsControl”类型的对象强制转换为“Windows.UI.Xaml.Controls.Image”类型

    我在此项目控件中放置了一个点击事件 以便在点击图像时查看图像 但是当我这样做时 我收到此错误 我该如何修复它 我尝试更改为项目图像但不存在 XAML 代码
  • 如何获取用星号定义的 WPF 网格列来剪辑内容?

    我有一个使用星号比例的网格控件 例如
  • 如何在Python中使用x和y坐标验证ES384 JWT签名

    我有一个 JWT 如下 Authorization Bearer eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCIsImtpZCI6IjQ0ODIzZjNkLTBiMDEtNGE2Yy1hODBlLWI5ZDNlOGE
  • 并行框架和避免错误共享

    最近 我回答了一个关于优化可能的并行方法来生成任意基数的每个排列的问题 我发布了类似的答案并行化 实施不佳代码块列表 有人几乎立即指出了这一点 这几乎肯定会给你带来错误的共享 并且可能会慢很多倍 归功于gjvdkamp https stac