非同步代理程式程式庫
非同步代理程式程式庫(或只提供 Agents 程式庫 )提供程式設計模型,可讓您增加已啟用並行的應用程式開發健全性。 代理程式程式庫是 C++ 樣板程式庫,可升級動作專案型程式設計模型和進程內訊息,以傳遞粗略資料流程和管道處理工作。 代理程式程式庫是以並行執行時間的排程和資源管理元件為基礎。
程式設計模型
代理程式程式庫可讓您透過以資料流程為基礎而非控制流程的非同步通訊模型連接隔離元件,以提供共用狀態的替代方案。 資料流程 是指當所有必要資料都可供使用時進行計算的程式設計模型; 控制流程 是指以預先決定的順序進行計算的程式設計模型。
資料流程程式設計模型與「訊息傳遞」的概念有關,其中程式的獨立元件可藉由傳送訊息相互通訊。
代理程式程式庫是由三個元件所組成: 非同步代理程式 、 非同步消息區塊 和 訊息傳遞函式 。 代理程式會維護狀態,並使用消息區塊和訊息傳遞函式彼此通訊,並與外部元件通訊。 訊息傳遞函式可讓代理程式從外部元件來回傳送和接收訊息。 非同步訊息區塊會保存訊息,並讓代理程式以同步處理的方式進行通訊。
下圖顯示兩個代理程式如何使用訊息區塊和訊息傳遞函式進行通訊。 在此圖中, agent1
使用 concurrency::send 函式和 平行存取::unbounded_buffer 物件,將訊息傳送至 agent2
。 agent2
會使用 concurrency::receive 函式來讀取訊息。 agent2
使用相同的方法將訊息傳送至 agent1
。 虛線箭號代表代理程式之間的資料流程。 實心箭號會將代理程式連接到他們寫入或讀取的訊息區塊。
本主題稍後會顯示實作此圖例的程式碼範例。
代理程式設計模型比其他並行和同步處理機制有數個優點,例如事件。 其中一個優點是,藉由使用訊息傳遞來傳輸物件之間的狀態變更,您可以隔離共用資源的存取權,進而改善延展性。 訊息傳遞的優點是,它會將同步處理系結至資料,而不是將它系結至外部同步處理物件。 這可簡化元件之間的資料傳輸,並可以消除應用程式中的程式設計錯誤。
使用代理程式程式庫的時機
當您有多個作業必須以非同步方式彼此通訊時,請使用 Agents 程式庫。 訊息區塊和訊息傳遞函式可讓您撰寫平行應用程式,而不需要鎖定等同步處理機制。 這可讓您專注于應用程式邏輯。
代理程式設計模型通常用於建立 資料管線 或 網路 。 資料管線是一系列元件,每個元件都會執行特定工作,以達成較大的目標。 資料流程管線中的每個元件都會在收到來自另一個元件的訊息時執行工作。 該工作的結果會傳遞至管線或網路中的其他元件。 元件可以使用其他程式庫的更精細並行功能,例如 平行模式程式庫 (PPL) 。
範例
下列範例會實作本主題稍早所示的圖例。
// 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);
}
這個範例會產生下列輸出:
agent1: sending request...
agent2: received 'request'.
agent2: sending response...
agent1: received '42'.
下列主題描述此範例中使用的功能。
[相關主題]
非同步代理程式
描述非同步代理程式在解決較大運算工作中的角色。
非同步訊息區
描述代理程式程式庫所提供的各種訊息區塊類型。
訊息傳遞函式
描述代理程式程式庫所提供的各種訊息傳遞常式。
如何:實作各種生產者-消費者模式
描述如何在應用程式中實作生產者-取用者模式。
如何:為呼叫和轉換程式類別提供工作函式
說明將工作函式提供給並行::call 和 concurrency::transformer 類別的 數種方式。
如何:在資料管線中使用轉換程式
示範如何在資料管線中使用 並行::transformer 類別。
如何:在已完成的工作之中選取
示範如何使用 concurrency::choice 和 concurrency::join 類別來選取第一個工作以完成搜尋演算法。
如何:定期傳送訊息
示範如何使用 concurrency::timer 類別定期傳送訊息。
如何:使用訊息區篩選條件
示範如何使用篩選來啟用非同步消息區塊來接受或拒絕訊息。
平行模式程式庫 (PPL)
描述如何在應用程式中使用各種平行模式,例如平行演算法。
並行執行階段
說明並行執行階段,它可簡化平行程式設計,並包含相關主題的連結。