C++ 多线程作业队列管理器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/565137/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Multithreaded job queue manager
提问by Marc Ditto
I need to manage CPU-heavy multitaskable jobs in an interactive application. Just as background, my specific application is an engineering design interface. As a user tweaks different parameters and options to a model, multiple simulations are run in the background and results displayed as they complete, likely even as the user is still editing values. Since the multiple simulations take variable time (some are milliseconds, some take 5 seconds, some take 10 minutes), it's basically a matter of getting feedback displayed as fast as possible, but often aborting jobs that started previously but are now no longer needed because of the user's changes have already invalidated them. Different user changes may invalidate different computations so at any time I may have 10 different simulations running. Somesimulations have multiple parts which have dependencies (simulations A and B can be seperately computed, but I need their results to seed simulation C so I need to wait for both A and B to finish first before starting C.)
我需要在交互式应用程序中管理占用大量 CPU 的多任务作业。作为背景,我的具体应用是一个工程设计界面。当用户调整模型的不同参数和选项时,多个模拟在后台运行并在完成时显示结果,甚至可能在用户仍在编辑值时也是如此。由于多次模拟需要不同的时间(有些是毫秒,有些需要 5 秒,有些需要 10 分钟),这基本上是尽快显示反馈的问题,但通常会中止以前开始但现在不再需要的作业,因为用户的更改已经使它们无效。不同的用户更改可能会使不同的计算无效,因此我随时可能运行 10 个不同的模拟。
I feel pretty confident that the code-level method to handle this kind of application is some kind of multithreaded job queue. This would include features of submitting jobs for execution, setting task priorities, waiting for jobs to finish, specifying dependencies (do this job, but only after job X and job Y have finished), canceling subsets of jobs that fit some criteria, querying what jobs remain, setting worker thread counts and priorities, and so on. And multiplatform support is very useful too.
我非常有信心处理这种应用程序的代码级方法是某种多线程作业队列。这将包括提交作业以供执行、设置任务优先级、等待作业完成、指定依赖项(执行此作业,但仅在作业 X 和作业 Y 完成后)、取消符合某些条件的作业子集、查询什么的功能作业保留,设置工作线程计数和优先级,等等。多平台支持也非常有用。
These are not new ideas or desires in software, but I'm at the early design phase of my application where I need to make a choice about what library to use for managing such tasks. I've written my own crude thread managers in the past in C (I think it's a rite of passage) but I want to use modern tools to base my work on, not my own previous hacks.
这些不是软件中的新想法或愿望,但我正处于应用程序的早期设计阶段,我需要选择使用哪个库来管理此类任务。我过去曾用 C 编写过我自己的粗略线程管理器(我认为这是一种通过仪式),但我想使用现代工具来建立我的工作,而不是我自己以前的黑客。
The first thought is to run to OpenMPbut I'm not sure it's what I want. OpenMP is great for parallelizing at a fine level, automatically unrolling loops and such. While multiplatform, it also invades your code with #pragmas. But mostly it's not designed for managing large tasks.. especially cancelling pending jobs or specifying dependencies. Possible, yes, but it's not elegant.
第一个想法是运行到OpenMP,但我不确定这是我想要的。OpenMP 非常适合精细级别的并行化、自动展开循环等。虽然是多平台的,但它也会通过 #pragmas 侵入您的代码。但大多数情况下,它不是为管理大型任务而设计的……尤其是取消挂起的作业或指定依赖项。可能,是的,但它并不优雅。
I noticed that Google Chrome uses such a job manager for even the most trivial tasks.The design goal seems to be to keep the user interaction thread as light and nimble as possible, so anything that can get spawned off asynchronously, should be. From looking at the Chrome source this doesn't seem to be a generic library, but it still is interesting to see how the design uses asynchronous launches to keep interaction fast. This is getting to be similar to what I'm doing.
我注意到Google Chrome 使用这样的作业管理器来处理最琐碎的任务。设计目标似乎是使用户交互线程尽可能轻巧灵活,因此任何可以异步生成的东西都应该如此。从 Chrome 源代码来看,这似乎不是一个通用库,但看看设计如何使用异步启动来保持快速交互仍然很有趣。这与我正在做的事情越来越相似。
There are a still other options:
还有其他选择:
Surge.Act:a Boost-like library for defining jobs. It builds on OpenMP, but does allow chaining of dependencies which is nice. It doesn't seem to feel like it's got a manager that can be queried, jobs cancelled, etc. It's a stale project so it's scary to depend on it.
Surge.Act:用于定义作业的类 Boost 库。它建立在 OpenMP 之上,但确实允许链接依赖项,这很好。它似乎没有可以查询的经理,取消工作等。这是一个陈旧的项目,因此依赖它是可怕的。
Job Queueis quite close to what I'm thinking of, but it's a 5 year old article, not a supported library.
Job Queue与我的想法非常接近,但它是一篇已有 5 年历史的文章,而不是受支持的库。
Boost.threadsdoes have nice platform independent synchronization but that's not a job manager. POCOhas very clean designs for task launching, but again not a full manager for chaining tasks. (Maybe I'm underestimating POCO though).
Boost.threads确实有很好的独立于平台的同步,但这不是一个作业管理器。POCO具有非常简洁的任务启动设计,但同样不是用于链接任务的完整管理器。(也许我低估了 POCO)。
So while there are options available, I'm not satisfied and I feel the urge to roll my own library again. But I'd rather use something that's already in existence. Even after searching (here on SO and on the net) I haven't found anything that feels right, though I imagine this must be a kind of tool that is often needed, so surely there's some community library or at least common design. On SO there's been some postsabout job queues, but nothing that seems to fit.
因此,虽然有可用的选项,但我并不满意,我有再次推出自己的图书馆的冲动。但我宁愿使用已经存在的东西。即使在搜索之后(在 SO 和网上)我也没有找到任何感觉正确的东西,尽管我想这一定是一种经常需要的工具,所以肯定有一些社区图书馆或至少是通用设计。在 SO 上有一些关于job queues 的帖子,但似乎没有什么合适的。
My post here is to ask you all what existing tools I've missed, and/or how you've rolled your own such multithreaded job queue.
我在这里的帖子是问你们所有我错过的现有工具,和/或你们如何推出自己的这种多线程作业队列。
回答by Crashworks
We had to build our own job queue system to meet requirements similar to yours ( UI thread must always respond within 33ms, jobs can run from 15-15000ms ), because there really was nothing out there that quite met our needs, let alone was performant.
我们必须构建自己的作业队列系统来满足与您类似的要求(UI 线程必须始终在 33 毫秒内响应,作业可以在 15-15000 毫秒之间运行),因为那里确实没有什么能完全满足我们的需求,更不用说性能了.
Unfortunately our code is about as proprietary as proprietary gets, but I can give you some of the most salient features:
不幸的是,我们的代码与专有代码一样具有专有性,但我可以为您提供一些最显着的功能:
- We start up one thread per core at the beginning of the program. Each pulls work from a global job queue. Jobs consist of a function object and a glob of associated data (really an elaboration on a func_ptr and void *). Thread 0, the fast client loop, isn't allowed to work on jobs, but the rest grab as they can.
- The job queue itself ought to be a lockless data structure, such as a lock-free singly linked list(Visual Studio comes with one). Avoid using a mutex; contention for the queue is surprisingly high, and grabbing mutexes is costly.
Pack up all the necessary data for the job into the job object itself -- avoid having pointer from the job back into the main heap, where you'll have to deal with contention between jobs and locks and all that other slow, annoying stuff. For example, all the simulation parameters should go into the job's local data blob. The results structure obviously needs to be something that outlives the job: you can deal with this either by a) hanging onto the job objects even after they've finished running (so you can use their contents from the main thread), or b) allocating a results structure specially for each job and stuffing a pointer into the job's data object. Even though the results themselves won't live in the job, this effectively gives the job exclusive access to its output memory so you needn't muss with locks.
Actually I'm simplifying a bit above, since we need to choreograph exactly which jobs run on which cores, so each core gets its own job queue, but that's probably unnecessary for you.
- 我们在程序开始时为每个内核启动一个线程。每个都从全局作业队列中提取工作。作业由一个函数对象和一组关联数据组成(实际上是对 func_ptr 和 void * 的详细说明)。线程 0,即快速客户端循环,不允许处理作业,但其余部分会尽可能地抓取。
- 作业队列本身应该是无锁数据结构,例如无锁单向链表(Visual Studio自带一个)。避免使用互斥锁;对队列的争用非常高,并且获取互斥锁的成本很高。
将作业的所有必要数据打包到作业对象本身中——避免将来自作业的指针放回到主堆中,在那里你必须处理作业和锁之间的争用以及所有其他缓慢、烦人的事情。例如,所有模拟参数都应该进入作业的本地数据 blob。结果结构显然需要比工作更持久:您可以通过以下方式处理此问题:a)即使在作业对象已完成运行后仍将其挂起(以便您可以使用主线程中的内容),或 b)为每个作业专门分配一个结果结构,并将一个指针填充到作业的数据对象中。即使结果本身不会存在于作业中,这也有效地为作业提供了对其输出内存的独占访问权限,因此您无需使用锁。
实际上我在上面进行了一些简化,因为我们需要准确编排哪些作业在哪些内核上运行,因此每个内核都有自己的作业队列,但这对您来说可能是不必要的。
回答by Ryan Graham
I rolled my own, based on Boost.threads. I was quite surprised by how much bang I got from writing so little code. If you don't find something pre-made, don't be afraid to roll your own. Between Boost.threads and your experience since writing your own, it might be easier than you remember.
我基于 Boost.threads 推出了自己的产品。我对编写这么少的代码所产生的巨大影响感到非常惊讶。如果你没有找到预制的东西,不要害怕自己动手。在 Boost.threads 和你自编写你自己的经验之后,它可能比你记得的要容易。
For premade options, don't forget that Chromiumis licensed very friendly, so you may be able to roll your own generic library around its code.
对于预制选项,不要忘记Chromium的许可非常友好,因此您可以围绕其代码推出自己的通用库。
回答by Rick
Microsoft is working on a set of technologies for the next Version of Visual Studio 2010 called the Concurrency Runtime, the Parallel Pattern Library and the Asynchronous Agents Library which will probably help. The Concurrency Runtime will offer policy based scheduling, i.e. allowing you to manage and compose multiple scheduler instances (similar to thread pools but with affinitization and load balancing between instances), the Parallel Pattern Library will offer task based programming and parallel loops with an STL like programming model. The Agents library offers an actor based programming model and has support for building concurrent data flow pipelines, i.e. managing those dependencies described above. Unfortunately this isn't released yet, so you can read about it on our team blogor watch some of the videos on channel9there is also a very large CTP that is available for download as well.
微软正在为下一个版本的 Visual Studio 2010 开发一组技术,称为并发运行时、并行模式库和异步代理库,它们可能会有所帮助。并发运行时将提供基于策略的调度,即允许您管理和组合多个调度程序实例(类似于线程池,但实例之间具有关联性和负载平衡),并行模式库将提供基于任务的编程和具有 STL 的并行循环,例如编程模型。Agents 库提供了一个基于actor 的编程模型,并支持构建并发数据流管道,即管理上述那些依赖关系。不幸的是,这还没有发布,所以你可以在我们的团队博客上阅读它或观看channel9 上的一些视频,还有一个非常大的 CTP 可供下载。
If you're looking for a solution today, Intel's Thread Building Blocks and boost's threading library are both good libraries and available now. JustSoftwareSolutionshas released an implementation of std::thread which matches the C++0x draft and of course OpenMP is widely available if you're looking at fine-grained loop based parallelism.
如果您今天正在寻找解决方案,Intel 的 Thread Building Blocks 和 boost 的线程库都是不错的库并且现在可用。JustSoftwareSolutions已经发布了一个 std::thread 的实现,它与 C++0x 草案相匹配,当然如果你正在研究基于细粒度循环的并行性,OpenMP 是广泛可用的。
The real challenge as other folks have alluded to is to correctly identify and decompose work into tasks suitable for concurrent execution (i.e. no unprotected shared state), understand the dependencies between them and minimize the contention that can occur on bottlenecks (whether the bottleneck is protecting shared stateor ensuring the dispatch loop of a work queue is low contention or lock-free)... and to do this without scheduling implementation details leaking into the rest of your code.
正如其他人所提到的,真正的挑战是正确识别工作并将其分解为适合并发执行的任务(即没有未受保护的共享状态),了解它们之间的依赖关系并最大限度地减少瓶颈上可能发生的争用(瓶颈是否正在保护共享状态或确保工作队列的调度循环是低争用或无锁的)......并且在不将调度实现细节泄漏到代码的其余部分的情况下做到这一点。
-Rick
-瑞克
回答by greyfade
Would something like threadpoolbe useful to you? It's based on boost::threads and basically implements a simple thread task queue that passes worker functions off to the pooled threads.
线程池之类的东西对你有用吗?它基于 boost::threads 并且基本上实现了一个简单的线程任务队列,它将工作函数传递给池化线程。
回答by Paul Morrison
You might want to look at Flow-Based Programming - it is based on data chunks streaming between asynchronous components. There are Java and C# versions of the driver, plus a number of precoded components. It is intrinsically multithreaded - in fact the only single-threaded code is within the components, although you can add timing constraints to the standard scheduling rules. Although it may be at too fine-grained a level for what you need, there may be stuff here you can use.
您可能想查看基于流的编程- 它基于异步组件之间的数据块流。有 Java 和 C# 版本的驱动程序,以及许多预编码组件。它本质上是多线程的——实际上唯一的单线程代码是在组件中,尽管您可以向标准调度规则添加时序约束。尽管对于您需要的内容而言,它的粒度可能过于精细,但这里可能有您可以使用的东西。
回答by timday
Take a look at boost::future(but see also this discussionand proposal) which looks like a really nice foundation for parallelism (in particular it seems to offer excellent support for C-depends-on-A-and-B type situations).
看一下boost::future(但也请参阅此讨论和提案),它看起来是并行性的一个非常好的基础(特别是它似乎为 C-depends-on-A-and-B 类型的情况提供了极好的支持) .
I looked at OpenMP a bit but (like you) wasn't convinced it would work well for anything but Fortran/C numeric code. Intel's Threading Building Blockslooked more interesting to me.
我看了一下 OpenMP,但(像你一样)不相信它适用于 Fortran/C 数字代码以外的任何东西。英特尔的线程构建块对我来说看起来更有趣。
If it comes to it, it's not too hard to roll your ownon top of boost::thread. [Explanation: a thread farm(most people would call it a pool) draws work from a thread-safe queueof functors (tasks or jobs). See the testsand benchmarkfor examples of use. I have some extra complication to (optionally) support tasks with priorities, and the case where executing tasks can spawn more tasks into the work queue (this makes knowing when all the work is actually completed a bit more problematic; the references to "pending" are the ones which can deal with the case). Might give you some ideas anyway.]
如果涉及到它,在 boost::thread 之上滚动你自己的并不难。[解释:线程农场(大多数人将其称为池)从一个线程安全的函子(任务或作业)队列中提取工作。有关使用示例,请参阅测试和基准测试。我有一些额外的复杂性(可选)支持具有优先级的任务,以及执行任务可以将更多任务产生到工作队列中的情况(这使得知道所有工作何时实际完成有点问题;对“待处理”的引用是可以处理案件的人)。反正可能会给你一些想法。]
回答by AdamK
There's plenty of distributed resource managers out there. The software that meets nearly all of your requirements is Sun Grid Engine. SGE is used on some of the worlds largest supercomputers and is in active development.
那里有很多分布式资源管理器。满足您几乎所有要求的软件是Sun Grid Engine。SGE 用于一些世界上最大的超级计算机,并且正在积极开发中。
There's also similar solutions in Torque, Platform LSF, and Condor.
在Torque、Platform LSF和Condor 中也有类似的解决方案。
It sounds like you may want to roll your own but there's plenty of functionality in all of the above.
听起来您可能想推出自己的产品,但上述所有功能都有很多功能。
回答by Shane Powell
You may like to look at Intel Thread Building Blocks. I beleave it does what you want and with version 2 it's Open Source.
您可能想查看英特尔线程构建块。我相信它可以满足您的需求,并且在第 2 版中它是开源的。
回答by Shane Powell
A little late to the punch perhaps, but take a look also at ThreadWeaver: http://en.wikipedia.org/wiki/ThreadWeaver
也许有点晚了,但也看看 ThreadWeaver:http: //en.wikipedia.org/wiki/ThreadWeaver
回答by KindaSorta
I've been looking for near the same requirements. I'm working on a game with 4x-ish mechanics and scheduling different parts of what gets done almost exploded my brain. I have a complex set of work that needs to get accomplished at different time resolutions, and to a different degree of actual simulation depending on what system/region the player has actively loaded. This means as the player moves from system to system, I need to load a system to the current high resolution simulation, offload the last system to a lower resolution simulation, and do the same for active/inactive regions of systems. The different simulations are big lists of population, political, military, and economic actions based on profiles of each entity. I'm going to try to describe my issue and my approach so far and I hope it's useful at describe an alternative for you or someone else. The rough outline of the structure I'm building will use the following:
我一直在寻找几乎相同的要求。我正在开发一个具有 4x 机制的游戏,并且安排完成的不同部分几乎让我的大脑爆炸。我有一组复杂的工作需要在不同的时间分辨率下完成,并根据玩家主动加载的系统/区域进行不同程度的实际模拟。这意味着当玩家从一个系统移动到另一个系统时,我需要将一个系统加载到当前的高分辨率模拟中,将最后一个系统卸载到一个较低分辨率的模拟中,并对系统的活动/非活动区域执行相同的操作。不同的模拟是基于每个实体的概况的人口、、军事和经济行动的大列表。到目前为止,我将尝试描述我的问题和我的方法,我希望它' 在为您或其他人描述替代方案时很有用。我正在构建的结构的粗略轮廓将使用以下内容:
- cpp-taskflow(A Modern C++ Parallel Task Programming Library) I'm going to make a library of modules that will be used as job construction parts. Each entry will have an API for initializing and destruction as well as pointers for communication. I'm hoping to write it in a way that they will be nest-able using the cpp-taskflow API to set-up all the dependencies at job creation time, but provide a means of live adjustment and having a kill-switch available. Most of what I'm making will be decision trees of state machines, or state machines of behavior trees so the job data structure will be settings and states of time-resolution tagged data pointing to actual stats and object values.
- FlatBuffersI'm looking to use this library to build a "job list entry" as well as an "object wrapper" system. Each entry in the job queues will be a flatbuffer object describing the work needed done(settings for the module), as well as containing the data(or shared pointers to the data) for the work that needs done. The object storage flatbuffers will contain the data that represents entity tables. For me, most of the actual data will me arrays that need deciding/working on. I'm also looking to use flatbuffers as a communication/control channel between threads. I'm torn on making a master "router" thread all the others communicate through, or each one containing their own, and having some mechanism of discovery.
- SQLiteSince only the active regions/systems need higher resolution work done, some of the background job lists the game will create(for thousands of systems and their entities) will be pretty large and long lived. 100's of thousands - millions of jobs(big in my mind), each requiring an unknown amount of time to complete. In my case, I don't care when they get done, as long as they all do(long campains). I plan on each thread getting a table of an in-memory sqlite db as a job queue. Each entry will contain a blob of flatbuffer work, a pointer to a buffer to notify upon completion, a pointer to a control buffer for updates, and other fields decorating the job item(location, data ranges, priority) that will get filled as the job entry makes new jobs, and as the items are consumed into the database. This give me a way I can create relational ties between jobs and simply construct queries if I need to re-work/update jobs, remove them and their dependencies, or update/re-order priorities or dependencies. All this being used in an sqlite db also means that at any time I can dump the whole thing to disk and reload it later, or switch to attaching to and processing it from disk. Additionally, this gives me access to a lot of search and ordering algorithmic work I'd normally need a bunch of different types of containers for. Being able to use SQL queries gives me a lot of options to process the jobs.
- cpp-taskflow(现代 C++ 并行任务编程库)我将创建一个模块库,用作作业构建部分。每个条目都有一个用于初始化和销毁的 API 以及用于通信的指针。我希望以一种可以使用 cpp-taskflow API 嵌套的方式编写它,以在创建作业时设置所有依赖项,但提供一种实时调整的方法并具有可用的终止开关。我正在制作的大部分内容将是状态机的决策树或行为树的状态机,因此作业数据结构将是指向实际统计数据和对象值的时间分辨率标记数据的设置和状态。
- FlatBuffers我希望使用这个库来构建“作业列表条目”以及“对象包装器”系统。作业队列中的每个条目将是一个 flatbuffer 对象,描述需要完成的工作(模块的设置),以及包含需要完成的工作的数据(或指向数据的共享指针)。对象存储 flatbuffers 将包含表示实体表的数据。对我来说,大部分实际数据都是需要决定/处理的数组。我还希望使用 flatbuffers 作为线程之间的通信/控制通道。我对制作一个主“路由器”线程让所有其他人通过它进行通信,或者每个人都包含自己的,并具有某种发现机制感到痛苦。
- SQLite由于只有活动区域/系统需要完成更高分辨率的工作,因此游戏将创建的一些后台工作列表(针对数千个系统及其实体)将非常大且寿命长。成百上千 - 数百万个工作(在我看来很大),每个工作都需要未知的时间来完成。就我而言,我不在乎他们什么时候完成,只要他们都这样做(长时间的活动)。我计划让每个线程获取一个内存中的 sqlite db 表作为作业队列。每个条目将包含一个 flatbuffer 工作的 blob,一个指向完成时通知的缓冲区的指针,一个指向更新的控制缓冲区的指针,以及装饰作业项的其他字段(位置、数据范围、优先级),这些字段将被填充为作业条目创建新作业,并且随着项目被消耗到数据库中。这给了我一种方法,我可以在作业之间创建关系联系,如果我需要重新工作/更新作业,删除它们及其依赖项,或者更新/重新排序优先级或依赖项,则可以简单地构建查询。在 sqlite db 中使用的所有这些也意味着我可以随时将整个内容转储到磁盘并稍后重新加载,或者切换到附加到磁盘并从磁盘处理它。此外,这让我可以访问很多搜索和排序算法工作,我通常需要一堆不同类型的容器。能够使用 SQL 查询为我提供了很多处理作业的选项。在 sqlite db 中使用的所有这些也意味着我可以随时将整个内容转储到磁盘并稍后重新加载,或者切换到附加到磁盘并从磁盘处理它。此外,这让我可以访问很多搜索和排序算法工作,我通常需要一堆不同类型的容器。能够使用 SQL 查询为我提供了很多处理作业的选项。在 sqlite db 中使用的所有这些也意味着我可以随时将整个内容转储到磁盘并稍后重新加载,或者切换到附加到磁盘并从磁盘处理它。此外,这让我可以访问很多搜索和排序算法工作,我通常需要一堆不同类型的容器。能够使用 SQL 查询为我提供了很多处理作业的选项。
The communication queue(as a db) is what I'm torn as to whether I should make access via the corresponding thread(each thread contains it's own messaging db, and the module API has locks/mutex abstracted for access), or have all updates, adds/removes, and communication via some master router thread into one large db. I have no idea which will give me the least headaches as far as mutexing and locks. I got a few days into making a monster spaghetti beast of shared pointers to sbuffer pools and lookup tables, so each thread had it's own buffer in, and separate out buffers. That's when I decided to just offload the giant list keeping to sqlite. Then I thought, why not just feed the flatbuffer objects of everything else into tables.
通信队列(作为数据库)是我是否应该通过相应的线程进行访问(每个线程包含它自己的消息传递数据库,并且模块 API 具有为访问抽象的锁/互斥锁)或所有通过一些主路由器线程更新、添加/删除和通信到一个大数据库中。我不知道就互斥锁和锁而言,哪个会给我带来最少的麻烦。我花了几天时间制作了一个包含指向缓冲池和查找表的共享指针的怪物意大利面野兽,因此每个线程都有自己的缓冲区,并分开缓冲区。那时我决定只卸载保存到 sqlite 的巨型列表。然后我想,为什么不把其他所有东西的 flatbuffer 对象输入到表格中。
Having almost everything in a db means from each module, I can write sql statements that represent the view of the data I need to work on as well as pivot on the fly as to how the data is worked on. Having the jobs themselves in a db means I can do the same for them as well. SQLite has multi-threading access, so using it as a Multithreaded job queue manager shouldn't be too much of a stretch.
在 db 中拥有几乎所有内容意味着来自每个模块,我可以编写 sql 语句来表示我需要处理的数据的视图,以及关于如何处理数据的动态透视。将工作本身放在数据库中意味着我也可以为他们做同样的事情。SQLite 具有多线程访问权限,因此将其用作多线程作业队列管理器应该不会太费力。
In summary, Cpp-Taskflow will allow you to setup complicated nested loops with dependency chaining and job-pool multithreading. Out of the box it comes with most of the structure you need. FlatBuffers will allow you to create job declarations and object wrappers easy to feed into stream-buffers as one unit of work and pass them between job threads, and SQLite will allow you to tag and queue the stream-buffer jobs into blob entries in a way that should allow adding, searching, ordering, updating, and removal with minimal work on your end. It also makes saving and reloading a breeze. Snapshots and roll-backs should also be doable, you just have to keep your mind wrapped around the order and resolution of events for the db.
总之,Cpp-Taskflow 将允许您使用依赖链和作业池多线程设置复杂的嵌套循环。开箱即用,它具有您需要的大部分结构。FlatBuffers 将允许您创建作业声明和对象包装器,它们易于作为一个工作单元提供给流缓冲区,并在作业线程之间传递它们,而 SQLite 将允许您以某种方式将流缓冲区作业标记并排队到 blob 条目中这应该允许您以最少的工作添加、搜索、排序、更新和删除。它还使保存和重新加载变得轻而易举。快照和回滚也应该是可行的,您只需要关注数据库事件的顺序和解决方案。
Edit: Take this with a grain of salt though, I found your question because I'm trying to accomplish what Crashworks described. I'm thinking of using affinity to open long living threads and have the master thread run the majority of the Cpp-Taskflow hierarchy work, feeding jobs to the others. I've yet to use the sqlite meothod of job-queue/control communication, that's just my plan so far.
编辑:尽管如此,但我发现了您的问题,因为我正在尝试完成 Crashworks 所描述的内容。我正在考虑使用关联来打开长期存在的线程,并让主线程运行大部分 Cpp-Taskflow 层次结构工作,将作业提供给其他线程。我还没有使用过作业队列/控制通信的 sqlite 方法,到目前为止,这只是我的计划。
I hope someone finds this helpful.
我希望有人觉得这有帮助。