matrix_multiply代码解析
matrix_multiply代碼解析
關(guān)于matrix_multiply
程序執(zhí)行代碼里兩個矩陣的乘法,并將相乘結(jié)果打印在屏幕上。
示例的主要目的是展現(xiàn)怎么實現(xiàn)一個自定義CPU計算任務(wù)。
參考:https://github.com/sogou/workflow
示例代碼
https://github.com/sogou/workflow/blob/master/tutorial/tutorial-08-matrix_multiply.cc
定義計算任務(wù)
定義計算任務(wù)需要提供3個基本信息,分別為INPUT,OUTPUT,和routine。
INPUT和OUTPUT是兩個模板參數(shù),可以是任何類型。routine表示從INPUT到OUTPUT的過程,定義如下:
template <class INPUT, class OUTPUT>
class __WFThreadTask
{
…
std::function<void (INPUT *,
OUTPUT *)> routine;
…
};
可以看出routine是一個簡單的從INPUT到OUTPUT的計算過程。INPUT指針不要求是const,但用戶也可以傳const INPUT *的函數(shù)。
比如一個加法任務(wù),就可這么做:
struct add_input
{
int x;
int y;
};
struct add_ouput
{
int res;
};
void add_routine(const add_input
*input, add_output *output)
{
output->res = input->x + input->y;
}
typedef
WFThreadTask<add_input, add_output> add_task;
在矩陣乘法的示例里,輸入是兩個矩陣,輸出為一個矩陣。其定義如下:
namespace algorithm
{
using Matrix =
std::vector<std::vector>;
struct MMInput
{
Matrix a;
Matrix b;
};
struct MMOutput
{
int error;
size_t m, n, k;
Matrix c;
};
void matrix_multiply(const MMInput *in,
MMOutput *out)
{
…
}
}
矩陣乘法存在有輸入矩陣不合法的問題,所以output里多了一個error域,用來表示錯誤。
生成計算任務(wù)
定義好輸入輸出的類型,以及算法的過程之后,就可以通過WFThreadTaskFactory工廠來產(chǎn)生計算任務(wù)了。
在WFTaskFactory.h里,計算工廠類的定義如下:
template <class INPUT, class OUTPUT>
class WFThreadTaskFactory
{
private:
using T =
WFThreadTask<INPUT, OUTPUT>;
public:
static T *create_thread_task(const
std::string& queue_name,
std::function<void (INPUT *,
OUTPUT *)> routine,
std::function<void (T *)> callback);
…
};
與之前的網(wǎng)絡(luò)工廠類或算法工廠類略有不同,這個類需要INPUT和OUTPUT兩個模板參數(shù)。
queue_name相關(guān)的知識在上一個示例里已經(jīng)有介紹。routine就是你的計算過程,callback是回調(diào)。
在示例里,看到了這個調(diào)用的使用:
using MMTask =
WFThreadTask<algorithm::MMInput,
algorithm::MMOutput>;
using namespace algorithm;
int main()
{
typedef
WFThreadTaskFactory<MMInput, MMOutput> MMFactory;
MMTask *task = MMFactory::create_thread_task(“matrix_multiply_task”,
matrix_multiply,
callback);
MMInput *input = task->get_input();
input->a = {{1, 2, 3}, {4, 5, 6}};
input->b = {{7, 8}, {9, 10}, {11, 12}};
…
}
產(chǎn)生了task之后,通過get_input()接口得到輸入數(shù)據(jù)的指針。這個可以類比網(wǎng)絡(luò)任務(wù)的get_req()。
任務(wù)的發(fā)起和結(jié)束什么,與網(wǎng)絡(luò)任務(wù)并沒有什么區(qū)別。同樣,回調(diào)也很簡單:
void callback(MMTask
*task)???? // MMtask =
WFThreadTask<MMInput, MMOutput>
{
MMInput *input = task->get_input();
MMOutput *output = task->get_output();
assert(task->get_state() ==
WFT_STATE_SUCCESS);
if (output->error)
printf(“Error: %d
%s\n”, output->error, strerror(output->error));
else
{
printf(“Matrix A\n”);
print_matrix(input->a,
output->m, output->k);
printf(“Matrix B\n”);
print_matrix(input->b,
output->k, output->n);
printf(“Matrix A *
Matrix B =>\n”);
print_matrix(output->c,
output->m, output->n);
}
}
普通的計算任務(wù)可以忽略失敗的可能性,結(jié)束狀態(tài)肯定是SUCCESS。
callback里簡單打印了輸入輸出。如果輸入數(shù)據(jù)不合法,則打印錯誤。
算法與協(xié)議的對稱性
在體系里,算法與協(xié)議在一個非常抽象的層面上是具有高度對稱性的。
有自定義算法的線程任務(wù),那顯然也存在自定義協(xié)議的網(wǎng)絡(luò)任務(wù)。
自定義算法要求提供算法的過程,而自定義協(xié)議則需要用戶提供序列化和反序列化的過程。
無論是自定義算法還是自定義協(xié)議,都必須強(qiáng)調(diào)算法和協(xié)議都是非常純粹的。
例如算法就是一個從INPUT到OUPUT的轉(zhuǎn)換過程,算法并不知道task,series等的存在。
HTTP協(xié)議的實現(xiàn)上,也只關(guān)心序列化反序列化,無需要關(guān)心什么是task。而是在http task里去引用HTTP協(xié)議。
線程任務(wù)與網(wǎng)絡(luò)任務(wù)的復(fù)合性
在這個示例里,通過WFThreadTaskFactory構(gòu)建了一個線程任務(wù)。可以說這是一種最簡單的計算任務(wù)構(gòu)建,大多數(shù)情況下也夠用了。
同樣,用戶可以非常簡單的定義一個自有協(xié)議的server和client。
但在上一個示例里看到,可以通過算法工廠產(chǎn)生一個并行排序任務(wù),這顯然不是通過一個routine就能做到的。
對于網(wǎng)絡(luò)任務(wù),比如一個kafka任務(wù),可能要經(jīng)過與多臺機(jī)器的交互才能得到結(jié)果,但對用戶來講是完全透明的。
所以,任務(wù)都是具有復(fù)合性的,如果你熟練使用框架,可以設(shè)計出很多復(fù)雜的組件出來。
總結(jié)
以上是生活随笔為你收集整理的matrix_multiply代码解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: runtime系统的Cello
- 下一篇: Timer定时器开发