Grab设计难点
grab设计难点
Background
抓图模块要实现的几个目标
- 并行处理,一边抓图一边处理
- 图优化,以删除冗余操作
可是现在设计的api用起来没那么方便,具体体现在
- 并行处理不完美,体现在用callback实现事件等待机制,这个callback有局限性
- 无法超过64个事件(因为依赖于Windows WiatForSingleObject)
- 无法处理Event里面套Event
- 图api用起来不方便,体现在
- 无法以统一的思路处理两种launch policy: async和deferred
- 参数传递累赘: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)));
}
他好像都有类似的问题,即
- 如果不运行该future,获取其数据会怎样呢?都会hang住吧。
- 有可能他的api设计的比较好,future不能直接获取值,只能通过block_on()之类的函数获取
- 可是我们的没有这种效果
- 用户可以声明一个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
- 并行处理不完美: asio可以做到异步处理
- 抓图应该有几个线程?
- 图api不方便:
- 处理两种launch policy: async和deferred
- 参数传递累赘:使用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;}
};
抓图应该有几个线程?
- 抓图,动马达,设置马达event
- 等图
- 如果全部异步化(即等图,和graph运行都用异步处理),该线程可以取消
- 如果是同步等event(即等图,和graph运行都用同步处理),可以在graph处理的地方循环等图
- 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两种策略?
- async是抓图的时候立刻起一个graph运行
- 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
- poll: 处理ready queue里的task,直到ready queue为空
- run: 处理ready queue和wait queue里的所有task完成
- tbb.wait: 处理ready queue里的task,直到ready queue为空
Outstanding tasks
并行处理不完美: asio可以做到异步处理- 图api不方便:
- 处理两种launch policy: async和deferred
- 参数传递累赘:使用Dependency Injection,解耦上下层的关系