ps-lite源码学习笔记
来源:互联网 发布:opencv java 高斯模糊 编辑:程序博客网 时间:2024/06/04 19:05
ps-lite代码解析
首先查看ps-lit的源码结构:
base
filter
kv
parameter
proto
ps
system
ps.h
ps_main.cc
其中,ps_main.cc是其程序入口,ps.h是其接口,其他文件夹则包含各个功能模块。下面详细阐释各部分。
ps_main.cc代码很短,如下所示:
#include "ps.h"
namespace ps {
App* App::Create(int argc,char *argv[]) {
App* app = new App();
if (ps::IsServerNode()) {
CreateServerNode(argc, argv);
}
return app;
}
} // namespace ps
int main(int argc,char *argv[]) {
ps::StartSystem(&argc, &argv);
int ret =ps::IsWorkerNode() ? WorkerNodeMain(argc, argv) :0;
ps::StopSystem();
return ret;
}
首先,只看main函数,main函数的流程很明晰,可以展示为下图:
可以发现,main函数主要用于创建WorkerNode,在main函数上面的代码中,我们注意到有一个app类,关于app类的定义,可见ps/app.h,这个类,在这里,这个Create用于创建SeverNode。
那么,main函数的功能不难理解,它就是用来创建WorkerNode和SeverNode的。
ps.h:接下来,我们展开接口函数ps.h,理解了它,结合main函数中的流程,我们就不难理解整个ps-lite的架构,首先观察其源码,笔者将整个接口分为4部分,分别是:
Worker node APIs
Server node APIs
Scheduler Node APIs(目前为空)
More Advanced APIs
由于其中Scheduler Node APIs 为空,所以我们分三部分来研究。
第一部分——Worker node APIs :
//Syncopts是push和pull操作的选项集
struct Syncopts{
std::vector<int> deps;
//deps是push操作的时间戳,只有当该操作被参数服务器处理时,才会修改其时间戳。
std::function<void()> callback;
//当收到参数服务器返回的响应时执行callback。
std::vector<Filter> filters;
//key-value过滤器用于减少通信开销
Filter* AddFilter(Filter::Type type);
//用于添加过滤器,使用举例:AddFilter(Filter::COMPRESSING);
int cmd = -1;
//-1表示无命令。
};
//KVWorker是用来收发参数服务器key-value对的缓存器。
template<typename Val>
class KVWorker{
explicit KVWorker(int id =0) {
cache_ = CHECK_NOTNULL((new KVCache<Key, Val>(id)));
}
//id是用来在参数服务器中寻找KVStore的唯一标识,负数ID的KVWorker为系统专用。//注:声明为explicit表示其不可被隐式转换。
~KVWorker() {delete cache_; }
// Basic Push and Pull
int Push(const std::vector<Key>& keys,
const std::vector<Val>& vals,
const SyncOpts& opts = SyncOpts()) {
// copy the data, then use the zero copy push
return ZPush(std::make_shared<std::vector<Key>>(keys),
std::make_shared<std::vector<Val>>(vals), opts);
}
//push操作将一串key-value对传到参数服务器。
//它是一个非阻塞调用,当要发送的信息进入系统的发送队列立刻返回。真正的push操作只在wait返回时或者提供的callback被调用时才结束。
int Pull(const std::vector<Key>& keys,
std::vector<Val>* vals,
const SyncOpts& opts = SyncOpts()) {
// copy the data, then use the zero copy pull
return ZPull(std::make_shared<std::vector<Key>>(keys), vals, opts);
}
//pull操作根据key将value从参数服务器取出。
//它是一个非阻塞调用,当要发送的信息进入系统的发送队列立刻返回。真正的pull操作只在wait返回时或者提供的callback被调用时才结束。
void Wait(int timestamp) {
cache_->Wait(timestamp);
}
//Wait操作用来阻塞下一个请求,直到当前请求完成。
// Zero-copy Push and Pull
//默认情况下,Push和pull操作都会先拷贝数据,然后用户程序可以重写或者删除数据。然而,有些情况下memcpy十分耗费时间,所以我们用ZPush和ZPull以减少时间,但需要注意的是,用户需要自己保持key和value的值不变直到请求完成。
int ZPush(const std::shared_ptr<std::vector<Key> >& keys,
const std::shared_ptr<std::vector<Val> >& vals,
const SyncOpts& opts = SyncOpts()) {
return cache_->Push(GetTask(opts), SArray<Key>(keys),SArray<Val>(vals), SArray<int>(),opts.callback);
}
int ZPull(const std::shared_ptr<std::vector<Key> >& keys,
std::vector<Val>* vals,
const SyncOpts& opts = SyncOpts()) {
return cache_->Pull(GetTask(opts), SArray<Key>(keys),
CHECK_NOTNULL(vals), NULL, opts.callback);
}
…
private:
Task GetTask(const SyncOpts& opts);
KVCache<Key, Val>* cache_;
};
int WorkerNodeMain(int argc,char *argv[]);
//WorkerNodeMain是一个WorkerNode的Main函数。
第二部分——Server node APIs :
//IOnlineHandle是一个用于处理请求的句柄例子。
template <typename Val, typename SyncVal>
class IOnlineHandle {
public:
IOnlineHandle() { }
virtual ~IOnlineHandle() { }
inline void Start(bool push, int timestamp,int cmd, void* msg) { }
//开始处理一个Worker的请求。
inline void Finish() { }
//请求已被处理。
inline void Init(Key key, Val& val) { }
//Handle初始化。
inline void Push(Key recv_key, Blob<const SyncVal> recv_val, Val& my_val) {…}
//处理来自worker节点的push请求
inline void Pull(Key recv_key, const Val& my_val, Blob<SyncVal>& send_val){…}
//处理来自worker节点的pull请求
inline void SetCaller(void *obj) { }
//接收caller
};
//Sever节点用OnlineServer存储key-value对,key-value对从worker发过来,被Handle依次接收,然后存储进KVStore中。
template <typename Val, typename SyncVal = Val,
typename Handle = IOnlineHandle<Val, SyncVal> >
class OnlineServer {
public:
OnlineServer(const Handle& handle = Handle(), int pull_val_len = 1, int id = 0) {…};
~OnlineServer() { }
KVStore* server() { return server_; }
private:
KVStore* server_ = NULL;
};
//Sever节点的main函数。
int CreateServerNode(int argc,char *argv[]);
第三部分——More Advanced APIs :
inline App* MyApp()
{ return Postoffice::instance().manager().app(); }
//返回当前节点运行的App
inline Node MyNode()
{ return Postoffice::instance().manager().van().my_node(); }
//返回当前节点的全局ID
inline std::string MyNodeID() {return MyNode().id(); }
//返回我的所有节点的ID
inline intIsWorkerNode()
{ return MyNode().role() == Node::WORKER; }
//判断当前节点是否为Worker节点
inline intIsServerNode()
{ return MyNode().role() == Node::SERVER; }
//判断当前节点是否为Sever节点
inline intIsSchedulerNode()
{ return MyNode().role() == Node::SCHEDULER; }
//判断当前节点是否为scheduler节点
inline std::string SchedulerID() {
return Postoffice::instance().manager().van().scheduler().id();}
//返回SchedulerID
inline int MyRank() { return MyNode().rank(); }
//返回节点所在组的rankID,
inline int RankSize() {
auto& mng =Postoffice::instance().manager();
return IsWorkerNode() ? mng.num_workers() : (IsServerNode() ? mng.num_servers() :1);}
//返回当前组的节点数。
inline int NumWorkers() { return FLAGS_num_workers; }
inline int NumServers() { return FLAGS_num_servers; }
inline void StartSystem(int* argc, char ***argv) {
ps::Postoffice::instance().Run(argc, argv);
}
inline voidStopSystem() {
ps::Postoffice::instance().Stop();
}
inline int RunSystem(int* argc, char ***argv) {
StartSystem(argc, argv); StopSystem();
return 0;
}
- ps-lite源码学习笔记
- ps-lite源码阅读笔记
- PS-Lite源码分析
- [Photon] Lite Application 源码阅读笔记
- PS学习笔记1
- PS学习笔记2
- ps学习笔记 一
- ps学习笔记 二
- ps基础学习笔记
- ps学习笔记 (快捷键)
- PS学习笔记------填充
- PS学习笔记----图层蒙版
- PS学习笔记
- ps学习笔记(一)
- ps学习笔记
- PS学习笔记
- PS学习笔记
- PS学习笔记
- 字符串右循环移位
- jquery验证篇
- 打开MySQL数据库远程访问的权限
- 【Java基础】Jar包结构结构分析和操作详解
- 怎么给文件夹加密码 电脑文件夹加密方法
- ps-lite源码学习笔记
- qt 的正则表达式 的使用
- asp.net自定义获取Get和Post请求的参数
- 散列表之散列函数
- linux常用查看硬件设备信息命令
- 利用onMeasure测量来实现图片拉伸永不变形,解决屏幕适配问题
- PostgreSQL学习手册
- 日语学习之沪江N3基础 20150626 -3
- Android代码混淆