Grab设计难点

grab设计难点

Background

抓图模块要实现的几个目标

  1. 并行处理,一边抓图一边处理
  2. 图优化,以删除冗余操作

可是现在设计的api用起来没那么方便,具体体现在

  1. 并行处理不完美,体现在用callback实现事件等待机制,这个callback有局限性
    1. 无法超过64个事件(因为依赖于Windows WiatForSingleObject)
    2. 无法处理Event里面套Event
  2. 图api用起来不方便,体现在
  3. 无法以统一的思路处理两种launch policy: async和deferred
  4. 参数传递累赘:parameter passing: Lots of para need pass from unit layer to sensor layer eg post processing, HDOA settings, conflict lighting –> OpticsEnv.getOpticsSetting(ioChannel) OpticsEnv.setOpticsSetting(ioChannel, post proocessing, HDOA settings, conflict lighting etc) 不同层次的接口很相近,但又不同。different grab pass different parameters to lower layer. although 如何能让每层之间的关系不要这么固定?如何能灵活一些?

GraphApi和rust future库的比较

rust future用法

fn main() {
    let future1 = future::ok::<u32, u32>(1)
        .map(|x| x + 3)
        .map_err(|e| println!("Error: {:?}", e))
        .and_then(|x| Ok(x - 3))
        .then(|res| {
          match res {
              Ok(val) => Ok(val + 3),
              err => err,
          }
        });
    let joined_future = future::join(future1, future::err::<u32, u32>(2));
    let val = block_on(joined_future);
    assert_eq!(val, (Ok(4), Err(2)));
}

他好像都有类似的问题,即

  1. 如果不运行该future,获取其数据会怎样呢?都会hang住吧。
    1. 有可能他的api设计的比较好,future不能直接获取值,只能通过block_on()之类的函数获取
  2. 可是我们的没有这种效果
    1. 用户可以声明一个Future<>然后不放到Graph里面就可以

GraphApi之对比用法

gmat和mat一起叫做future,一个GraphApi函数相当于一async函数, 一个graph相当于次block_on操作。

GraphApi 对应rust future
gmat和mat future
GraphApi函数 async函数
graph 一次block_on操作
获取输出的值通过 graph.run(ins, outs) 获取future的值通过 let value = block_on(xx)
可以在另外的线程获取输出的值,通过 outs[i].get()
Pros:适合多线程,跟已有老的代码共存
Cons:容易出错
没有对应的用法
Cons:必须全部异步
Pros:安全无副作用
Pros:可以做图优化 没有对应的用法
   
   

我们的难点是我们的graph的输入输出不是那么明显,出了问题要运行时才能检测,因为我们的都是一种mat类型

Idea

  1. 并行处理不完美: asio可以做到异步处理
  2. 抓图应该有几个线程?
  3. 图api不方便:
  4. 处理两种launch policy: async和deferred
  5. 参数传递累赘:使用Dependency Injection,解耦上下层的关系

Proposal

并行处理不完美: asio可以做到异步处理

接口上添加setAsioMode()功能

	class Options
	{
	public:
		typedef boost::function<int (std::vector<SharedFuture<Mat>> const &ins, std::vector<int> const &masks)> WaitFunc;

		Options():asioMode_(false)
		{
		}
		template <class T>
		Options& setWait(T t){asioMode_ = false; wait = t; return *this;}
		Options& setAsioMode(){asioMode_ = true; return *this;}
	
	};

抓图应该有几个线程?

  1. 抓图,动马达,设置马达event
  2. 等图
    1. 如果全部异步化(即等图,和graph运行都用异步处理),该线程可以取消
    2. 如果是同步等event(即等图,和graph运行都用同步处理),可以在graph处理的地方循环等图
  3. Graph处理

综上分析,需要两到三个线程

图api不方便

想到一个办法,就是设计如下类似的api. 一定程度上简化了代码

class Graph
{
public:
	class Node
	{
		
	public:
		// Get Gmat
		// Note no need provide non const version, as gmat should not be modified once created
		const GraphApi::GMat &gmat() const { return gmat_; }
		boost::optional<GraphApi::SharedFuture<GraphApi::Mat>> &mat() { return mat_; }

		// Set Mat
		void set(GraphApi::Mat const &m)
	};
	Node createInput();
	void run(std::vector<Node> &outNodes)

private:
	std::vector<GraphApi::GMat> gins_;
	std::vector<GraphApi::SharedFuture<GraphApi::Mat>> ins_;
};

处理两种launch policy: async和deferred

如何实现defer和async两种策略?

  1. async是抓图的时候立刻起一个graph运行
  2. defer抓图的时候不运行,需要的时候运行。是讲defer相关部分拆成另一个graph?如何保证没有overlap?如果两个graph有重叠那就惨了

提供用法2

// 创建graph节点
Graph g;
auto roi = g.createInput();
auto image = g.createInput();
auto profile = reconstruct(image, roi);

GGraph gg(g.gins(), gouts);
// 用法1:
// 如果input没有ready,下面的函数就会hang
gg.run(g.ins(), profile);

// 用法2:
// 如果让他不hang,可以参考两步。类似于tbb
// flowgraph或者asio。一步叫try_put,用来放某些输入,一步叫poll(),用来将能够处理的放到queue
// image grab module

// 抓图模块设置图像
image.set(im); 	 // 内部执行-->gg.set(index of image, im)

//抓完图后处理
gg.poll();    

// inspection module设置roi
roi.set(roi); gg.poll(); 

poll vs run vs tbb.wait

  1. poll: 处理ready queue里的task,直到ready queue为空
  2. run: 处理ready queue和wait queue里的所有task完成
  3. tbb.wait: 处理ready queue里的task,直到ready queue为空

Outstanding tasks

  1. 并行处理不完美: asio可以做到异步处理
  2. 图api不方便:
  3. 处理两种launch policy: async和deferred
  4. 参数传递累赘:使用Dependency Injection,解耦上下层的关系

Powered by Jekyll and Theme by solid

本站总访问量