Sdílet prostřednictvím


Knihovna asynchronních agentů

Knihovna asynchronních agentů (nebo jen Knihovna agentů) poskytuje programovací model, který umožňuje zvýšit odolnost vývoje aplikací s podporou souběžnosti. Knihovna agentů je knihovna šablon jazyka C++, která podporuje programovací model založený na objektech actor a předávání zpráv v procesu pro hrubě odstupňované úlohy toku dat a kanálování. Knihovna agentů vychází ze součástí plánování a správy prostředků modulu Concurrency Runtime.

Programovací model

Knihovna agentů poskytuje alternativy ke sdílenému stavu tím, že umožňuje připojit izolované komponenty prostřednictvím asynchronního komunikačního modelu založeného na toku dat místo toku řízení. Tok dat odkazuje na programovací model, kde jsou výpočty provedeny, když jsou k dispozici všechna požadovaná data; tok řízení odkazuje na programovací model, ve kterém jsou výpočty provedeny v předem určeném pořadí.

Programovací model toku dat souvisí s konceptem předávání zpráv, kdy nezávislé komponenty programu vzájemně komunikují odesláním zpráv.

Knihovna agentů se skládá ze tří komponent: asynchronních agentů, asynchronních bloků zpráv a funkcí předávání zpráv. Agenti udržují stav a používají bloky zpráv a funkce předávání zpráv ke komunikaci mezi sebou a s externími komponentami. Funkce předávání zpráv umožňují agentům odesílat a přijímat zprávy z externích komponent a z těchto externích komponent. Asynchronní zprávy blokují zprávy a umožňují agentům komunikovat synchronizovaným způsobem.

Následující obrázek ukazuje, jak dva agenti používají ke komunikaci bloky zpráv a funkce předávání zpráv. Na tomto obrázku agent1 odešle zprávu agent2 pomocí funkce concurrency::send a objektu concurrency::unbounded_buffer . agent2používá funkci concurrency::receive ke čtení zprávy. agent2používá stejnou metodu k odeslání zprávy .agent1 Přerušované šipky představují tok dat mezi agenty. Plné šipky spojují agenty s bloky zpráv, které zapisují nebo čtou.

The components of the Agents Library.

Příklad kódu, který implementuje tento obrázek, je znázorněn dále v tomto tématu.

Programovací model agenta má několik výhod oproti jiným mechanismům souběžnosti a synchronizace, například událostí. Jednou z výhod je to, že pomocí předávání zpráv přenáší změny stavu mezi objekty, můžete izolovat přístup ke sdíleným prostředkům a tím zlepšit škálovatelnost. Výhodou předávání zpráv je, že spojuje synchronizaci s daty místo jejich vázání k externímu objektu synchronizace. To zjednodušuje přenos dat mezi komponentami a může eliminovat programovací chyby ve vašich aplikacích.

Když použít knihovnu agentů

Knihovnu Agents použijte, pokud máte více operací, které musí vzájemně komunikovat asynchronně. Bloky zpráv a funkce předávání zpráv umožňují psát paralelní aplikace bez nutnosti synchronizace mechanismů, jako jsou zámky. Díky tomu se můžete zaměřit na logiku aplikace.

Programovací model agenta se často používá k vytváření datových kanálů nebo sítí. Datový kanál je řada komponent, z nichž každý provádí určitou úlohu, která přispívá k většímu cíli. Každá komponenta v kanálu toku dat funguje, když obdrží zprávu z jiné komponenty. Výsledek této práce se předá jiným komponentám v kanálu nebo síti. Komponenty můžou používat jemněji odstupňované funkce souběžnosti z jiných knihoven, například knihovny PPL (Parallel Patterns Library).

Příklad

Následující příklad implementuje obrázek uvedený výše v tomto tématu.

// basic-agents.cpp
// compile with: /EHsc
#include <agents.h>
#include <string>
#include <iostream>
#include <sstream>

using namespace concurrency;
using namespace std;

// This agent writes a string to its target and reads an integer
// from its source.
class agent1 : public agent 
{
public:
   explicit agent1(ISource<int>& source, ITarget<wstring>& target)
      : _source(source)
      , _target(target)
   {
   }

protected:
   void run()
   {
      // Send the request.
      wstringstream ss;
      ss << L"agent1: sending request..." << endl;
      wcout << ss.str();

      send(_target, wstring(L"request"));

      // Read the response.
      int response = receive(_source);

      ss = wstringstream();
      ss << L"agent1: received '" << response << L"'." << endl;
      wcout << ss.str();

      // Move the agent to the finished state.
      done();
   }

private:   
   ISource<int>& _source;
   ITarget<wstring>& _target;
};

// This agent reads a string to its source and then writes an integer
// to its target.
class agent2 : public agent 
{
public:
   explicit agent2(ISource<wstring>& source, ITarget<int>& target)
      : _source(source)
      , _target(target)
   {
   }

protected:
   void run()
   {
      // Read the request.
      wstring request = receive(_source);

      wstringstream ss;
      ss << L"agent2: received '" << request << L"'." << endl;
      wcout << ss.str();

      // Send the response.
      ss = wstringstream();
      ss << L"agent2: sending response..." << endl;
      wcout << ss.str();

      send(_target, 42);

      // Move the agent to the finished state.
      done();
   }

private:   
   ISource<wstring>& _source;
   ITarget<int>& _target;
};

int wmain()
{
   // Step 1: Create two message buffers to serve as communication channels
   // between the agents.
   
   // The first agent writes messages to this buffer; the second
   // agents reads messages from this buffer.
   unbounded_buffer<wstring> buffer1;

   // The first agent reads messages from this buffer; the second
   // agents writes messages to this buffer.
   overwrite_buffer<int> buffer2;

   // Step 2: Create the agents.
   agent1 first_agent(buffer2, buffer1);
   agent2 second_agent(buffer1, buffer2);

   // Step 3: Start the agents. The runtime calls the run method on
   // each agent.
   first_agent.start();
   second_agent.start();

   // Step 4: Wait for both agents to finish.
   agent::wait(&first_agent);
   agent::wait(&second_agent);
}

Tento příklad vytvoří následující výstup:

agent1: sending request...
agent2: received 'request'.
agent2: sending response...
agent1: received '42'.

Následující témata popisují funkce použité v tomto příkladu.

Asynchronní agenti
Popisuje roli asynchronních agentů při řešení větších výpočetních úloh.

Asynchronní bloky zpráv
Popisuje různé typy bloků zpráv, které poskytuje knihovna agentů.

Funkce pro předávání zpráv
Popisuje různé rutiny předávání zpráv, které poskytuje knihovna agentů.

Postupy: Implementace různých vzorů producent–příjemce
Popisuje, jak ve vaší aplikaci implementovat vzor producenta a příjemce.

Postupy: Poskytování pracovních funkcí třídám call a transformer
Ukazuje několik způsobů, jak poskytnout pracovní funkce souběžnosti::call a concurrency::transformer třídy.

Postupy: Použití transformace v datovém kanálu
Ukazuje, jak používat třídu concurrency::transformer v datovém kanálu.

Postupy: Výběr z dokončených úloh
Ukazuje, jak pomocí třídy concurrency::choice a concurrency::join vybrat první úkol pro dokončení vyhledávacího algoritmu.

Postupy: Odesílání zpráv v pravidelných intervalech
Ukazuje, jak pomocí třídy concurrency::timer odeslat zprávu v pravidelných intervalech.

Postupy: Použití filtru bloku zpráv
Ukazuje, jak pomocí filtru povolit asynchronní blok zpráv přijímat nebo odmítat zprávy.

Knihovna PPL (Parallel Patterns Library)
Popisuje, jak ve svých aplikacích používat různé paralelní vzory, jako jsou paralelní algoritmy.

Concurrency Runtime
Popisuje modul Concurrency Runtime, který zjednodušuje paralelní programování a obsahuje odkazy na související témata.