如何在parallel.for中强制执行有序执行序列?

2023-12-09

我有一个简单的并行循环来做一些事情,然后我将结果保存到文件中。

object[] items; // array with all items
object[] resultArray = new object[numItems];
Parallel.For(0, numItems, (i) => 
{ 
    object res = doStuff(items[i], i);
    resultArray[i] = res;
});

foreach (object res in resultArray)
{
    sequentiallySaveResult(res);
}

为了保存,我需要按正确的顺序写入结果。通过将结果放入resultArray,结果的顺序又正确了。

然而,由于结果相当大并且占用大量内存。 我想按顺序处理这些项目,例如四个线程启动并处理项目 1-4,下一个空闲线程处理项目 5,依此类推。

这样,我可以启动另一个线程,监视数组中接下来需要写入的项目(或者每个线程可以在一个项目完成时发出一个事件),这样我就可以开始写入第一个结果,而后面的项目则被写入仍在处理,然后释放内存。

Parallel.For 是否可以按给定顺序处理项目?我当然可以使用concurentQueue,将所有索引按正确的顺序放入其中并手动启动线程。

但如果可能的话,我想保留“Parallel.For”实现中关于使用多少线程等的所有自动化。

免责声明:我无法切换到ForEach,我需要i.

编辑#1:
目前,执行顺序是完全随机的,一个例子:

Processing item 1/255
Processing item 63/255
Processing item 32/255
Processing item 125/255
Processing item 94/255
Processing item 156/255
Processing item 187/255
Processing item 249/255
...

编辑#2:
已完成工作的更多详细信息:

我处理灰度图像并需要提取每个“层”(上例中的项目)的信息,因此我从 0 到 255(对于 8 位)并对图像执行任务。

我有一个类可以同时访问像素值:

 unsafe class UnsafeBitmap : IDisposable
    {

        private BitmapData bitmapData;
        private Bitmap gray;
        private int bytesPerPixel;
        private int heightInPixels;
        private int widthInBytes;
        private byte* ptrFirstPixel;

        public void PrepareGrayscaleBitmap(Bitmap bitmap, bool invert)
        {
            gray = MakeGrayscale(bitmap, invert);

            bitmapData = gray.LockBits(new Rectangle(0, 0, gray.Width, gray.Height), ImageLockMode.ReadOnly, gray.PixelFormat);
            bytesPerPixel = System.Drawing.Bitmap.GetPixelFormatSize(gray.PixelFormat) / 8;
            heightInPixels = bitmapData.Height;
            widthInBytes = bitmapData.Width * bytesPerPixel;
            ptrFirstPixel = (byte*)bitmapData.Scan0;
        }

        public byte GetPixelValue(int x, int y)
        {
            return (ptrFirstPixel + ((heightInPixels - y - 1) * bitmapData.Stride))[x * bytesPerPixel];
        }

        public void Dispose()
        {
            gray.UnlockBits(bitmapData);
        }
    }

循环是

UnsafeBitmap ubmp; // initialized, has the correct bitmap
int numLayers = 255;
int bitmapWidthPx = 10000;
int bitmapHeightPx = 10000;
object[] resultArray = new object[numLayer];
Parallel.For(0, numLayers, (i) => 
{ 
        for (int x = 0; x < bitmapWidthPx ; x++)
    {
        inLine = false;
        for (int y = 0; y < bitmapHeightPx ; y++)
        {
            byte pixel_value = ubmp.GetPixelValue(x, y);
            
            if (i <= pixel_value && !inLine)
            {
                result.AddStart(x,y);
                inLine = true;
            }
            else if ((i > pixel_value || y == Height - 1) && inLine)
            {
                result.AddEnd(x, y-1);
                inLine = false;
            }
        }
    }
    result_array[i] = result;
});

foreach (object res in resultArray)
{
    sequentiallySaveResult(res);
}

我还想启动一个线程进行保存,检查接下来需要写入的项目是否可用,写入它,从内存中丢弃。为此,如果处理按顺序开始,以便结果到达,那就太好了roughly为了。如果第 5 层的结果到达倒数第二个,我必须等待写入第 5 层(以及后续所有层)直到最后。

如果有 4 个线程启动,则开始处理第 1-4 层,当一个线程完成后,开始处理第 5 层,下一个第 6 层,依此类推,结果将或多或少以相同的顺序出现,我可以开始将结果写入文件并将其从内存中丢弃。


The Parallel类知道如何并行化工作负载,但不知道如何合并处理的结果。所以我建议使用PLINQ反而。您要求以原始顺序保存结果并与处理同时进行,这使得它比平时有点棘手,但它仍然是完全可行的:

IEnumerable<object> results = Partitioner
    .Create(items, EnumerablePartitionerOptions.NoBuffering)
    .AsParallel()
    .AsOrdered()
    .WithMergeOptions(ParallelMergeOptions.NotBuffered)
    .Select((item, index) => DoStuff(item, index))
    .AsEnumerable();

foreach (object result in results)
{
    SequentiallySaveResult(result);
}

解释:

  1. The AsOrdered需要运算符来按原始顺序检索结果。
  2. The WithMergeOptions需要运算符来防止结果缓冲,以便在结果可用时立即保存它们。
  3. The Partitioner.Create是必需的,因为数据源是数组,PLINQ 默认对数组进行分区静态地。这意味着数组被分成多个范围,并分配一个线程来处理每个范围。一般来说,这是一个很好的性能优化,但在这种情况下,它违背了及时有序检索结果的目的。所以一个dynamic需要分区器,以从开始到结束顺序枚举源。
  4. The EnumerablePartitionerOptions.NoBuffering配置可防止 PLINQ 使用的工作线程一次获取多个项目(这是默认的 PLINQ 分区技巧,称为“块分区”)。
  5. The AsEnumerable并不是真正需要的。它的存在只是为了表示并行处理的结束。这foreach接下来处理的是ParallelQuery<object> as IEnumerable<object> anyway.

由于需要所有这些技巧,并且由于此解决方案不够灵活,以防您稍后需要在处理管道中添加更多并发异构步骤,因此我建议记住逐步升级的选项TPL数据流图书馆。它是一个在并行处理领域解锁许多强大选项的库。

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

如何在parallel.for中强制执行有序执行序列? 的相关文章

  • 何时使用 =default 使析构函数默认?

    尽管对构造函数使用 default 对我来说很清楚 即强制编译器在其他构造函数存在时创建默认构造函数 但我仍然无法理解这两种类型的析构函数之间的区别 那些使用 default 的 那些没有显式定义并由编译器自动生成的 我唯一想到的是 gro
  • 为什么在创建矩阵类时使用向量不好?

    对于我的矩阵类 我做了 template
  • 平滑滚动.net 表单

    您好 我正在 net 中使用表单 并且在运行时动态添加大量链接标签 我将这些链接标签添加到面板并将该面板添加到 winform 当链接标签的数量增加时 表单会显示一个自动滚动条 垂直 现在 当我使用自动滚动向下滚动时 表单在滚动时不会更新其
  • EF Core 通过完全替换断开集合导航属性的更新

    使用 EF Core 5 0 我有一个 SPA 页面 可以加载Group实体及其集合Employee来自 API 的实体 var groupToUpdate await context Groups Include g gt g Emplo
  • VS 程序在调试模式下崩溃,但在发布模式下不崩溃?

    我正在 VS 2012 中运行以下程序来尝试 Thrust 函数查找 include cuda runtime h include device launch parameters h include
  • 找不到 assimp-vc140-mt.dll ASSIMP

    我已经从以下位置下载了 Assimp 项目http assimp sourceforge net main downloads html http assimp sourceforge net main downloads html Ass
  • ASP.Net Core 内容配置附件/内联

    我正在从 WebAPI 控制器返回一个文件 Content Disposition 标头值自动设置为 附件 例如 处置 附件 文件名 30956 pdf 文件名 UTF 8 30956 pdf 当它设置为附件时 浏览器将要求保存文件而不是打
  • 时间:2019-03-17 标签:c#ThreadSafeDeepCopy

    我一直在阅读很多其他问题以及大量谷歌搜索 但我一直无法找到明确的解决方案 根据我读过的一些最佳实践 类的静态方法应该创建线程安全的 并且实例成员应该将线程安全留给消费者 我想为该类实现深度复制方法 该类本身还有其他引用类型成员 有没有什么方
  • std::forward_as_tuple 将参数传递给 2 个构造函数

    我想传递多个参数以便在函数内构造两个对象 以同样的方式std pair
  • 检查 RoutedEvent 是否有任何处理程序

    我有一个自定义 Button 类 当单击它时 打开特定窗口 它总是执行相同的操作 我添加了一个可以在按钮的 XAML 中分配的 Click 事件 就像常规按钮一样 当它被单击时 我想执行 Click 事件处理程序 如果已分配 否则我想执行默
  • 如何在c的case语句中使用省略号?

    CASE expr no commas ELLIPSIS expr no commas 我在c的语法规则中看到了这样的规则 但是当我尝试重现它时 int test float i switch i case 1 3 printf hi 它失
  • 我可以让 ungetc 取消阻止阻塞的 fgetc 调用吗?

    我想在收到 SIGUSR1 后使用 ungetc 将 A 字符重新填充到标准输入中 想象一下我有充分的理由这样做 调用 foo 时 stdin 中的阻塞读取不会被收到信号时的 ungetc 调用中断 虽然我没想到它会按原样工作 但我想知道是
  • 新任务中使用的依赖注入服务

    我在需要时使用依赖项注入来访问我的服务 但我现在想要创建一个并发任务 但这会由于依赖项注入对象及其生命周期而导致问题 我读过这篇文章 标题 防止多线程 Link http mehdi me ambient dbcontext in ef6
  • 每个数据库多个/单个 *.edmx 文件

    我有一个通过 ADO net 数据服务与数据库交互的项目 数据库很大 近 150 个具有依赖关系的表 该项目几年前开始 当时使用的是数据集 现在我们正在转向实体模型关系 由于我们添加了更多需要使用的表 该模型正在不断增长 这是管理这一切的正
  • C++0x中disable_if在哪里?

    Boost 两者都有enable if and disable if 但 C 0x 似乎缺少后者 为什么它被排除在外 C 0x 中是否有元编程工具允许我构建disable if按照enable if 哦 我刚刚注意到std enable i
  • 使我的 COM 程序集调用异步

    我刚刚 赢得 了在当前工作中维护用 C 编码的遗留库的特权 这个dll 公开使用 Uniface 构建的大型遗留系统的方法 除了调用 COM 对象之外别无选择 充当此遗留系统与另一个系统的 API 之间的链接 在某些情况下 使用 WinFo
  • 使用 QtWebEngine 将 C++ 对象暴露给 Qt 中的 Javascript

    使用 QtWebkit 可以通过以下方式将 C 对象公开给 JavascriptQWebFrame addToJavaScriptWindowObject如中所述https stackoverflow com a 20685002 5959
  • xsi:type 属性搞乱了 C# XML 反序列化

    我使用 XSD exe 根据 XML 架构 xsd 文件 自动生成 C 对象 我正在反序列化 OpenCover 输出 但其中一个部分类未正确生成 这是导致异常的行
  • 从 JavaScript 中的 OnClientClick 事件中阻止 C# 中的 asp:Button OnClick 事件?

    我有一个asp Button在我的网页上 它调用 JavaScript 函数和代码隐藏方法 后者进行调用以导航到另一个页面 在 JavaScript 函数中 我正在检查条件 如果不满足这个条件 我想中止导航 以便OnClick方法未被调用
  • Java 和/C++ 在多线程方面的差异

    我读过一些提示 多线程实现很大程度上取决于您正在使用的目标操作系统 操作系统最终提供了多线程能力 比如Linux有POSIX标准实现 而windows32有另一种方式 但我想知道编程语言水平的主要不同 C似乎为同步提供了更多选择 例如互斥锁

随机推荐

  • 理解结构等价

    我有两种类型的结构等价思想我正在努力理解 VAR 1 int VAR 2 pointer to VAR 1 所以在这里 我觉得它们在结构上是等效的 因为从技术上讲 这些类型都指向整数类型 对吗 但如果你有类似的东西 VAR 3 pointe
  • Crystal Report Viewer 打印/导出按钮在 ASP.NET MVC 应用程序中不起作用

    我的 MVC 应用程序使用推送模型和 CR 查看器进行报告 在查看器中显示报告时一切都很好 但是打印 导出按钮给出了 JavaScript 错误 此操作不支持对象 我正在使用 VS 2008 和 MVC 这发生在我的开发环境中 有任何想法吗
  • Android 中的自定义字体(适用于整个应用程序)[重复]

    这个问题在这里已经有答案了 我有这个 android 代码 其中有许多类 每个类都有不同的视图 我们可以进入设置并根据所选的字体更改其字体 目前仅预装的 Android 字体可用 有没有办法稍微调整我的代码 以便我可以添加 ttf 文件并将
  • 如何知道 Azure 服务器是否使用 TLS 1.2

    我们有一个托管在 Azure 服务器中的 Web 应用程序 使用 Azure 服务器中的 api 出于安全目的 我们想知道服务器是否处于 tls 1 2 之下 我想对于非云服务器 我们只需在 regedit 中查看即可知道 我已经看到有关如
  • 线程是内核对象吗?

    在这本书中 我读到每个实例Thread类实际上正在分配一个内核对象 这是使用的开销之一Thread 据我所知 线程不是内核对象 在这种情况下只有进程是内核对象 进程包含的线程不是内核对象 有人可以解释一下吗 线程首先是一个托管对象 你知道S
  • 如何将 JavaScript 侦听器添加到 PrimeFaces Ajax 事件

    我想通过javascript方法监听pickList传输事件 侦听器与 java bean 配合良好
  • Django + Mongo + Docker 获取 pymongo.errors.ServerSelectionTimeoutError

    我一直在努力使用 Django Djongo Mongodb 和 Docker Compose 运行一个简单的应用程序 我的设置如下所示 docker compose yml services mongodb image mongo lat
  • PackageMaker 的“在包中包含根”选项实际上有什么作用?

    我正在为 OS X 应用程序制作安装程序 但无法理解 PackageMaker 的 UI 我的 PackageMaker 版本是 3 0 4 与 Lion 和 Xcode 4 1 一起运行 其中一个选项尤其让我感到困惑 这是编辑包内容时的
  • 为什么我必须最后调用 super -dealloc,而不是首先调用?

    正确的例子 void dealloc viewController release window release super dealloc 错误的例子 void dealloc super dealloc viewController r
  • 删除QListView背景

    我想删除我的 QListView 的背景 以便可以看到下面的背景 我怎样才能做到这一点 I tried setAttribute Qt WA NoSystemBackground and setAttribute Qt WA NoBackg
  • 通过pywin32将pandas数据框写入word文档表

    我目前正在编写一个脚本 需要写入 docx 文件以进行演示 我使用 pandas 来处理脚本中的所有数据计算 我希望使用 PyWIN32 将 pandas 数据帧写入 word docx 文件中书签处的表中 数据框由浮点数组成 伪代码是这样
  • 如何创建其中包含永久提示的编辑文本

    我有一个编辑文本 用户在其中输入金额 我想要做的是在其前面设置一个用户不可编辑的文本视图值 例如 INR 然后用户将在其前面输入金额 我希望 edittext 看起来像下面的那样 我怎样才能做到这一点
  • Laravel 4 Auth with Facebook(无密码身份验证)

    我正在尝试使用 Laravel 4 设置一个通过 Facebook 登录的身份验证系统 我正在为 Laravel 4 使用 madewithlove laravel oauth2 包 当然 当用户使用 Facebook 登录时 没有密码可以
  • ElementTree(1.3.0) Python中XML解析的高效方法

    我正在尝试解析一个巨大的 XML 文件 20MB 3GB 文件是来自不同仪器的样本 所以 我正在做的是从文件中查找必要的元素信息并将它们插入到数据库 Django 中 我的文件样本的一小部分 命名空间存在于所有文件中 文件的有趣特征是它们有
  • ASP.NET MVC 5 错误处理

    我们想要处理 403 错误 404 错误以及由于以下原因导致的所有错误MySpecialDomainException并为所有其他错误 包括 IIS 配置中的错误 提供默认错误页面 所有错误都应该返回正确的 Razor 视图 如果有一个Er
  • 通量存储或操作(或两者)是否应该接触外部服务?

    如果商店保持自己的状态并能够调用网络和数据存储服务 在这种情况下 这些操作只是愚蠢的消息传递者 OR 存储是否应该是来自操作的不可变数据的愚蠢接收者 并且操作是在外部源之间获取 发送数据的操作 在这种情况下 存储将充当视图模型 并且能够聚合
  • 循环数组并将连续数字分组到另一个数组 SWIFT 4 中的最佳方法?

    我试图找出使用 SWIFT 4 循环数字数组 获取任何连续数字的范围并将其添加到新数组的最有效方法 我可以进行标准循环检查 但我相信我可以使用地图过滤器 有人能指出我正确的方向吗 开始 myNumbersArray Int 1 2 3 4
  • 如何在UIWebView中设置自定义字体?

    我在资源中有一个字体 并将其加载到 UIFont 中 我想知道如何使用这个 UIFont 作为我的 UIWebView 的默认字体 提前致谢 如果您使用网页在WebView中显示 这就是我要做的 使用 HTML 页面的标题创建一个字符串 在
  • 查找并单击具有更改 CSS 选择器的元素 (python)

    我正在编写一个脚本 需要单击页面的某个元素 但是 CSS 选择器每天都会随着元素更改其位置而更改 今天它的名字叫 PPTAmFCTable gt tbody nth child 1 gt tr nth child 11 gt td nth
  • 如何在parallel.for中强制执行有序执行序列?

    我有一个简单的并行循环来做一些事情 然后我将结果保存到文件中 object items array with all items object resultArray new object numItems Parallel For 0 n