matrix_multiply代码解析

关于matrix_multiply

程序执行代码里两个矩阵的乘法,并将相乘结果打印在屏幕上。

示例的主要目的是展现怎么实现一个自定义CPU计算任务。

参考:https://github.com/sogou/workflow

示例代码

https://github.com/sogou/workflow/blob/master/tutorial/tutorial-08-matrix_multiply.cc

定义计算任务

定义计算任务需要提供3个基本信息,分别为INPUT,OUTPUT,和routine。

INPUT和OUTPUT是两个模板参数,可以是任何类型。routine表示从INPUT到OUTPUT的过程,定义如下:

template <class INPUT, class OUTPUT>

class __WFThreadTask

{

...

std::function<void (INPUT *,
OUTPUT *)> routine;

...

};

可以看出routine是一个简单的从INPUT到OUTPUT的计算过程。INPUT指针不要求是const,但用户也可以传const INPUT *的函数。

比如一个加法任务,就可这么做:

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<double>>;

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域,用来表示错误。

生成计算任务

定义好输入输出的类型,以及算法的过程之后,就可以通过WFThreadTaskFactory工厂来产生计算任务了。

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);

...

};

与之前的网络工厂类或算法工厂类略有不同,这个类需要INPUT和OUTPUT两个模板参数。

queue_name相关的知识在上一个示例里已经有介绍。routine就是你的计算过程,callback是回调。

在示例里,看到了这个调用的使用:

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}};

...

}

产生了task之后,通过get_input()接口得到输入数据的指针。这个可以类比网络任务的get_req()。

任务的发起和结束什么,与网络任务并没有什么区别。同样,回调也很简单:

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);

}

}

普通的计算任务可以忽略失败的可能性,结束状态肯定是SUCCESS。

callback里简单打印了输入输出。如果输入数据不合法,则打印错误。

算法与协议的对称性

在体系里,算法与协议在一个非常抽象的层面上是具有高度对称性的。

有自定义算法的线程任务,那显然也存在自定义协议的网络任务。

自定义算法要求提供算法的过程,而自定义协议则需要用户提供序列化和反序列化的过程。

无论是自定义算法还是自定义协议,都必须强调算法和协议都是非常纯粹的。

例如算法就是一个从INPUT到OUPUT的转换过程,算法并不知道task,series等的存在。

HTTP协议的实现上,也只关心序列化反序列化,无需要关心什么是task。而是在http task里去引用HTTP协议。

线程任务与网络任务的复合性

在这个示例里,通过WFThreadTaskFactory构建了一个线程任务。可以说这是一种最简单的计算任务构建,大多数情况下也够用了。

同样,用户可以非常简单的定义一个自有协议的server和client。

但在上一个示例里看到,可以通过算法工厂产生一个并行排序任务,这显然不是通过一个routine就能做到的。

对于网络任务,比如一个kafka任务,可能要经过与多台机器的交互才能得到结果,但对用户来讲是完全透明的。

所以,任务都是具有复合性的,如果你熟练使用框架,可以设计出很多复杂的组件出来。

matrix_multiply代码解析的更多相关文章

  1. VBA常用代码解析

    031 删除工作表中的空行 如果需要删除工作表中所有的空行,可以使用下面的代码. Sub DelBlankRow() DimrRow As Long DimLRow As Long Dimi As L ...

  2. [nRF51822] 12、基础实验代码解析大全 · 实验19 - PWM

    一.PWM概述: PWM(Pulse Width Modulation):脉冲宽度调制技术,通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形. PWM 的几个基本概念: 1) 占空比:占空比是指 ...

  3. [nRF51822] 11、基础实验代码解析大全 · 实验16 - 内部FLASH读写

     一.实验内容: 通过串口发送单个字符到NRF51822,NRF51822 接收到字符后将其写入到FLASH 的最后一页,之后将其读出并通过串口打印出数据. 二.nRF51822芯片内部flash知识 ...

  4. [nRF51822] 10、基础实验代码解析大全 · 实验15 - RTC

    一.实验内容: 配置NRF51822 的RTC0 的TICK 频率为8Hz,COMPARE0 匹配事件触发周期为3 秒,并使能了TICK 和COMPARE0 中断. TICK 中断中驱动指示灯D1 翻 ...

  5. [nRF51822] 9、基础实验代码解析大全 · 实验12 - ADC

    一.本实验ADC 配置 分辨率:10 位. 输入通道:5,即使用输入通道AIN5 检测电位器的电压. ADC 基准电压:1.2V. 二.NRF51822 ADC 管脚分布 NRF51822 的ADC ...

  6. java集合框架之java HashMap代码解析

     java集合框架之java HashMap代码解析 文章Java集合框架综述后,具体集合类的代码,首先以既熟悉又陌生的HashMap开始. 源自http://www.codeceo.com/arti ...

  7. Kakfa揭秘 Day8 DirectKafkaStream代码解析

    Kakfa揭秘 Day8 DirectKafkaStream代码解析 今天让我们进入SparkStreaming,看一下其中重要的Kafka模块DirectStream的具体实现. 构造Stream ...

  8. linux内存管理--slab及其代码解析

    Linux内核使用了源自于 Solaris 的一种方法,但是这种方法在嵌入式系统中已经使用了很长时间了,它是将内存作为对象按照大小进行分配,被称为slab高速缓存. 内存管理的目标是提供一种方法,为实 ...

  9. MYSQL常见出错mysql_errno()代码解析

    如题,今天遇到怎么一个问题, 在理论上代码是不会有问题的,但是还是报了如上的错误,把sql打印出來放到DB中却可以正常执行.真是郁闷,在百度里面 渡 了很久没有相关的解释,到时找到几个没有人回复的 & ...

随机推荐

  1. hdu4982 暴搜+剪枝(k个数和是n,k-1个数的和是平方数)

    题意:       给你两个数n,k问你是否怎在这样一个序列:      (1)这个序列有k个正整数,且不重复.      (2)这k个数的和是n.      (3)其中有k-1个数的和是一个平方数. ...

  2. 用 vitePress 快速创建一个文档项目

    其实开发一个项目最需要的就是操作文档,文档的质量决定了项目的开发流程,开发规范等等. 对于前端框架来说,文档最友好的还是vue,不仅是中国人的框架,而且文档支持了中文.仔细查看 Vue 的官方文档,还 ...

  3. JAVA的安装

    1.从JAVA官网 下载 注意选择自己需要的版本 2.百度云盘 链接:https://pan.baidu.com/s/1deOFGN1xB0mgz6s2mTRXdA 提取码:ke97 安装JAVA J ...

  4. 【python】Leetcode每日一题-二叉搜索树节点最小距离

    [python]Leetcode每日一题-二叉搜索树节点最小距离 [题目描述] 给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 . 示例1: 输入:root = [4 ...

  5. 【编译原理】求First和Follow

    写这篇博客的原因,是因为考试前以为自己已经将这个问题弄清楚了,但是,考试的时候,发现自己还是不会,特别是求follow集合.虽然考试结束了,希望屏幕前的你,可以真正理解这个问题. 码字和做视频都不容易 ...

  6. android之Tween Animation

    android Tween Animation有四种,AlphaAnimation(透明度动画).ScaleAnimation(尺寸伸缩动画).TranslateAnimation(位移动画).Rot ...

  7. lombok,Invalid byte tag in constant pool: 19

    今天偶到一个奇怪的问题: 三台生产服务器部署同样的代码,同样的tomcat ,jdk等环境. 其中有一台服务器启动时报lombok-1.18.6.jar!   Invalid byte tag in ...

  8. Redis学习笔记六:持久化实验(AOF,RDB)

    作者:Grey 原文地址:Redis学习笔记六:持久化实验(AOF,RDB) Redis几种持久化方案介绍和对比 AOF方式:https://blog.csdn.net/ctwctw/article/ ...

  9. EasyBPM打印模板的缓存问题

    业务平台EasyBPM(易实管理软件)有一个功能是模板打印的功能.就是可以使用一个docx格式的模板,输出一个docx格式的单据的文档. 打印的逻辑是先从服务端获取模板,如果没有对应的模板,就提示先上 ...

  10. MongoDB&#183;Windows下管理员密码重置解决方案

    阅文时长 | 1.07分钟 字数统计 | 1730.4字符 主要内容 | 1.问题切入 2.详细步骤 3.声明与参考资料 『MongoDB·Windows下管理员密码重置解决方案』 编写人 | SCs ...