草庐IT

c++ - 用于基于任务的并行性的通用 c++11 函数包装器

coder 2024-02-10 原文

我正在实现一个工作窃取算法,并正在编写一个通用函数包装器,它将 promise 作为包装器模板的可变参数之一。我想使用这些函数包装器创建任务,并让每个节点使用 promise 与依赖节点进行通信。每个节点都维护一个依赖节点和 promise / future 的列表。每个节点都可以通过检查是否已设置所有 future 来运行。 promises 可以根据函数包装器正在返回不同对象的工作而有所不同。如果可以将单个算法分解为单独的操作,例如读取消息和解码消息、对对象执行检查、返回所有检查的结果,则这些操作中的每一个都将返回不同的 promise (对象、 bool 值、结果)。

C++ Concurrency in Action 这本书有一个函数包装器实现,但是它不处理这个用例。在其他在线引用资料中,我看到了对像 std::promise 这样的 promise 的硬编码引用,它只是一种类型。

有人可以建议我如何编写包装器来实现以下目标......

void add(int a, int b, std::promise<int>&& prms)
{
   int res = a + b;
   try {
      prms.set_value(res);
   }
   catch(...)
   {
      prms.set_exception(std::current_exception());
   }
}

int main()
{
   std::promise<int> prms;
   std::future<int> fut = prms.get_future();
   FunctionWrapper myFunctor(a, 10, 20, std::move(prms));

   // add the functor to the queue and it will be retrieved by a thread
   // that executes the task. since i have the future, i can pass it to the 
   // dependent worknode
}

我尝试编写如下代码......但在让它工作时遇到了困难。

#ifndef FUNCTIONWRAPPER_HPP
#define FUNCTIONWRAPPER_HPP

template<typename F, typename R, typename... Args>
class FunctionWrapper
{
  class implbase
  {
  public:
    virtual ~implbase();
    virtual R execute(Args...)=0;
  };

  class impl : public implbase
  {
  public:
    impl(F&& f) : func(std::move(f)) {}
    virtual R execute(Args... args) { return func(args...); }

  private:
    F func;
  };

  std::shared_ptr<impl> internalFunc;

public:
  FunctionWrapper(F&& f) : internalFunc(0)
  {
    internalFunc = new impl<F, R, Args...>(f);
  }

  FunctionWrapper(const FunctionWrapper& other)
    : internalFunc(std::move(other.internalFunc))
  {}

  ~FunctionWrapper()
  {
    if(internalFunc)
      delete internalFunc;
  }

  R operator()(Args... args)
  {
    return internalFunc->execute(args...);
  }

  void swap(FunctionWrapper& other)
  {
    impl<R, Args...>* tmp = internalFunc;
    internalFunc = other.internalFunc;
    other.internalFunc = tmp;
  }

  FunctionWrapper& operator=(const FunctionWrapper& other)
  {
    FunctionWrapper(other).swap(*this);
    return *this;
  }

  FunctionWrapper& operator=(const F& f)
  {
    FunctionWrapper(f).swap(*this);
    return *this;
  }
};

#endif // FUNCTIONWRAPPER_HPP

最佳答案

C++11 有一个包装器可以做到这一点!它叫做packaged_task .

它的作用是包装一个可调用对象(函数对象、lambda、函数指针、绑定(bind)表达式等...)并通过匹配的 get_future() 方法为您提供 future 传入函数的返回类型。

考虑以下示例:

#include <thread>
#include <future>
#include <functional>
#include <iostream>

using namespace std;

int add(int a, int b)
{
    return a + b;
}

int main()
{
    // Create a std::packaged_task and grab the future out of it.
    packaged_task<int()> myTask(bind(add, 10, 20));
    future<int> myFuture = myTask.get_future();

    // Here, is where you would queue up the task in your example.
    // I'll launch it on another thread just to demonstrate how.
    thread myThread(std::move(myTask));
    myThread.detach();

    // myFuture.get() will block until the task completes.
    // ...or throw if the task throws an exception.
    cout << "The result is: " << myFuture.get() << endl;
    return 0;
}

如您所见,我们没有传递 promise,而是依靠 packaged_task 来创建 promise 并为我们提供 future 。

此外,使用绑定(bind)表达式使我们能够有效地将参数传递给任务以保留直到它被调用。

使用 packaged_task 还会将 future 推送异常的负担交给 packaged_task。这样,您的函数就不需要调用 set_exception()。他们只需要返回或抛出。

关于c++ - 用于基于任务的并行性的通用 c++11 函数包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13998059/

有关c++ - 用于基于任务的并行性的通用 c++11 函数包装器的更多相关文章

  1. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  2. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby - 如何使用 RSpec::Core::RakeTask 创建 RSpec Rake 任务? - 2

    如何使用RSpec::Core::RakeTask初始化RSpecRake任务?require'rspec/core/rake_task'RSpec::Core::RakeTask.newdo|t|#whatdoIputinhere?endInitialize函数记录在http://rubydoc.info/github/rspec/rspec-core/RSpec/Core/RakeTask#initialize-instance_method没有很好的记录;它只是说:-(RakeTask)initialize(*args,&task_block)AnewinstanceofRake

  5. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  6. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  7. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  8. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  9. ruby-on-rails - Cucumber 是否只是 rspec 的包装器以帮助将测试组织成功能? - 2

    只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您

  10. ruby - inverse_of 是否适用于 has_many? - 2

    当我使用has_one时,它​​工作得很好,但在has_many上却不行。在这里您可以看到object_id不同,因为它运行了另一个SQL来再次获取它。ruby-1.9.2-p290:001>e=Employee.create(name:'rafael',active:false)ruby-1.9.2-p290:002>b=Badge.create(number:1,employee:e)ruby-1.9.2-p290:003>a=Address.create(street:"123MarketSt",city:"SanDiego",employee:e)ruby-1.9.2-p290

随机推荐