paxos 练手 推进中
学习https://github.com/huoyu820125/SecondPaxos 自己编写网络版本
在学习过程将此代码的线程 锁等改成c++11 就不用包含那么多文件
主要更改如下
1 // MyPaxos.cpp: 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include <iostream> 6 #include <chrono> 7 #include <mutex> 8 #include <thread> 9 #include "Acceptor.h" 10 #include "Proposer.h" 11 12 13 paxos::Proposer p[11]; 14 paxos::Acceptor a[11]; 15 int finishedCount = 0; 16 std::mutex l[11]; 17 18 std::mutex printlock; 19 20 void Proposer(int id) { 21 paxos::Proposer &proposer = p[(int)id]; 22 paxos::PROPOSAL value = proposer.GetProposal(); 23 paxos::PROPOSAL lastValue; 24 25 26 int acceptorId[11]; 27 int count = 0; 28 29 while (true) { 30 value = proposer.GetProposal();//拿到提议 31 printlock.lock(); 32 std::cout << "Proposer" << (int)id << "号开始(Propose阶段):提议=[编号:" << value.serialNum 33 << ",提议:" << value.value << "]\n"; 34 printlock.unlock(); 35 count = 0; 36 int i = 0; 37 38 for (i = 0; i < 11; i++) 39 { 40 /* 41 * 发送消息到第i个acceptor 42 * 经过一定时间达到acceptor,sleep(随机时间)模拟 43 * acceptor处理消息,mAcceptors[i].Propose() 44 * 回应proposer 45 * 经过一定时间proposer收到回应,sleep(随机时间)模拟 46 * proposer处理回应mProposer.proposed(ok, lastValue) 47 */ 48 //经过随机时间,消息到达了mAcceptors[i] 49 std::this_thread::sleep_for(std::chrono::milliseconds(rand() % 100) ); 50 l[i].lock(); 51 bool ok = a[i].Propose(value.serialNum, lastValue); 52 l[i].unlock(); 53 std::this_thread::sleep_for(std::chrono::milliseconds(rand() % 100)); 54 //处理Propose回应 55 if (!proposer.Proposed(ok, lastValue)) //重新开始Propose阶段 56 { 57 std::this_thread::sleep_for(std::chrono::milliseconds(rand() % 100)); 58 //为了降低活锁,多等一会让别的proposer有机会完成自己的2阶段批准 59 break; 60 } 61 paxos::PROPOSAL curValue = proposer.GetProposal();//拿到提议 62 if (curValue.value != value.value)//acceptor本次回应可能推荐了一个提议 63 { 64 printlock.lock(); 65 std::cout << "Proposer" << (int)id << "号修改了提议:提议=[编号:" << 66 curValue.serialNum << ",提议:" << curValue.value << "]\n"; 67 printlock.unlock(); 68 } 69 acceptorId[count++] = i;//记录愿意投票的acceptor 70 if (proposer.StartAccept()) 71 { 72 if (0 == rand() % 2) break; 73 } 74 } 75 //检查有没有达到Accept开始条件,如果没有表示要重新开始Propose阶段 76 if (!proposer.StartAccept()) continue; 77 //开始Accept阶段 78 //发送Accept消息到所有愿意投票的acceptor 79 value = proposer.GetProposal(); 80 printlock.lock(); 81 std::cout << "Proposer" << (int)id << "号开始(Accept阶段):提议=[编号:" << 82 value.serialNum << ",提议:" << value.value << "]\n"; 83 printlock.unlock(); 84 for (i = 0; i < count; i++) 85 { 86 //发送accept消息到acceptor 87 std::this_thread::sleep_for(std::chrono::milliseconds(rand() % 100));//经过随机时间,accept消息到达acceptor 88 //处理accept消息 89 l[acceptorId[i]].lock(); 90 bool ok = a[acceptorId[i]].Accept(value); 91 l[acceptorId[i]].unlock(); 92 std::this_thread::sleep_for(std::chrono::milliseconds(rand() % 100));//经过随机时间,accept回应到达proposer 93 //处理accept回应 94 if (!proposer.Accepted(ok)) //重新开始Propose阶段 95 { 96 std::this_thread::sleep_for(std::chrono::milliseconds(rand() % 100));///为了降低活锁,多等一会让别的proposer有机会完成自己的2阶段批准 97 break; 98 } 99 if (proposer.IsAgree())//成功批准了提议 100 { 101 printlock.lock(); 102 std::cout << "Proposer" << (int)id << "号批准了提议:最终提议 = [编号:" << 103 value.serialNum << ",提议:" << value.value << "]\n"; 104 printlock.unlock(); 105 return ; 106 } 107 } 108 } 109 return ; 110 } 111 112 int main() 113 { 114 int i = 0; 115 std::cout << "11个Proposer, 11个Acceptor准备进行Paxos\n"<< 116 "每个Proposer独立线程,Acceptor不需要线程\n"<< 117 "Proposer线程中等待随机时间:表示与Acceptor的通信时间\n"<< 118 "Proposer线程中调用Acceptor.Proposed()表示拿到了Propose请求结果\n"<< 119 "Proposer线程中调用Acceptor.Accepted()表示拿到了Accept请求结果\n"<< 120 "Proposer被批准后结束线程,其它线程继续投票最终,全部批准相同的值,达成一致。\n"; 121 122 paxos::PROPOSAL value; 123 for (i = 0; i < 11; i++) 124 { 125 p[i].SetPlayerCount(11, 11); 126 value.serialNum = value.value = i + 1; 127 p[i].StartPropose(value); 128 } 129 130 std::thread t[11]; 131 for (i = 0; i < 11; i++) { 132 t[i] = std::thread(Proposer, i); 133 } 134 for (i = 0; i < 11; i++) { 135 t[i].join(); 136 } 137 while (true) { 138 std::this_thread::sleep_for(std::chrono::seconds(1)); 139 } 140 141 142 143 return 0; 144 }
View Code
20180513添加
根据视频 paxos和分布式系统_1024x768_2.00M_h.264
添加自写代码 vs2017 boost1.65编译
方案1 单点接收多点提交 二段提交 抢占提交权
// Accepter.cpp: 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <ctime> #include <iostream> #include <string> #include <memory> #include <mutex> #include <thread> #include <boost/asio.hpp>using boost::asio::ip::tcp;const int default_port = 9687;#pragma pack (1) //提议数据结构 typedef struct PROPOSAL {int index; //当前请求的阶段 int epoch; //流水号,1开始递增,保证全局唯一int value; //提议内容 }PROPOSAL;typedef struct ACCEPTSAL {int epoch; //流水号,1开始递增,保证全局唯一int value; //提议内容 }ACCEPTSAL; #pragma pack()enum INDEX {INIT_INDEX = 1,PREPARE_INDEX,ACCEPT_INDEX,FINISH_INDEX,ERROR_INDEX = -1, };int current_index = PREPARE_INDEX; ACCEPTSAL g_ServerRecord = {-1,-1 }; boost::asio::io_service io_service; std::mutex g_mtx; int acceptepoch = -1; //==========================================================void HandlePropose(std::shared_ptr<tcp::socket> socket) {PROPOSAL buf = { -1,-1,-1 };ACCEPTSAL tmpAcpsal = { -1,-1 };try {while (1) {boost::asio::read(*socket, boost::asio::buffer(&buf, sizeof(buf)));{std::lock_guard<std::mutex> lock(g_mtx);//prepare阶段if (buf.index == PREPARE_INDEX) {if (g_ServerRecord.epoch <= buf.epoch && g_ServerRecord.value == -1) {//更新最新的prepare epochg_ServerRecord.epoch = buf.epoch;current_index = ACCEPT_INDEX;}}else if (buf.index == ACCEPT_INDEX && (-1 == g_ServerRecord.value)) {if ((buf.epoch >= g_ServerRecord.epoch)) {g_ServerRecord.value = buf.value;current_index = FINISH_INDEX;}}//拷贝accepter记录tmpAcpsal = g_ServerRecord;}//回复boost::asio::write(*socket, boost::asio::buffer(&tmpAcpsal, sizeof(tmpAcpsal)));}}catch (std::exception& e) {std::cerr << e.what() << std::endl;return;} }int main() {try {tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), default_port));for (;;) {std::shared_ptr<tcp::socket> psocket = std::make_shared<tcp::socket>(io_service);acceptor.accept(*psocket);std::thread t(HandlePropose,psocket);t.detach();}}catch (std::exception& e) {std::cerr << e.what() << std::endl;}return 0; }
accepter
// Proposer.cpp: 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <ctime> #include <iostream> #include <string> #include <memory> #include <mutex> #include <thread> #include <boost/asio.hpp>using boost::asio::ip::tcp;const std::string default_port = "9687";#pragma pack (1) //提议数据结构 typedef struct PROPOSAL {int index; //当前请求的阶段 int epoch; //流水号,1开始递增,保证全局唯一int value; //提议内容 }PROPOSAL;typedef struct ACCEPTSAL {int epoch; //流水号,1开始递增,保证全局唯一int value; //提议内容 }ACCEPTSAL; #pragma pack()enum INDEX {INIT_INDEX = 1,PREPARE_INDEX,ACCEPT_INDEX,FINISH_INDEX,ERROR_INDEX = -1, };//========================================================int main() {try {boost::asio::io_service io_service;tcp::resolver resolver(io_service);tcp::resolver::query query("127.0.0.1", default_port.c_str());tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);tcp::socket socket(io_service);boost::asio::connect(socket, endpoint_iterator);for (;;) {PROPOSAL pro = { PREPARE_INDEX ,1,99 };ACCEPTSAL tmpAcpsal = { -1,-1 };boost::system::error_code error;boost::asio::write(socket, boost::asio::buffer(&pro,sizeof(pro)), error);size_t len = socket.read_some(boost::asio::buffer(&tmpAcpsal,sizeof(tmpAcpsal)), error);if (error == boost::asio::error::eof)break; // Connection closed cleanly by peer.else if (error)throw boost::system::system_error(error); // Some other error.if (tmpAcpsal.epoch == pro.epoch) {pro.index = ACCEPT_INDEX;boost::asio::write(socket, boost::asio::buffer(&pro, sizeof(pro)), error);size_t len = socket.read_some(boost::asio::buffer(&tmpAcpsal, sizeof(tmpAcpsal)), error);}if (tmpAcpsal.value != -1) {std::cout << " value is " << tmpAcpsal.value << std::endl;system("pause");return 1;}else {std::cerr << " value is " << tmpAcpsal.value << " . Error !!!" << std::endl;system("pause");return 1;}}}catch (std::exception& e) {std::cerr << e.what() << std::endl;}system("pause");return 0; }
propose
缺点 若抢占的propose 出现故障 则无法释放锁
方案2 单点接受多点提交 二段提交 根据epoch抢占提交权 若获取提交权的proposer出现故障 将会被拥有更高epoch的propose替代
// Accepter.cpp: 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <ctime> #include <iostream> #include <string> #include <memory> #include <mutex> #include <thread> #include <boost/asio.hpp>using boost::asio::ip::tcp;const int default_port = 9687;#pragma pack (1) //提议数据结构 typedef struct PROPOSAL {int index; //当前请求的阶段 int epoch; //流水号,1开始递增,保证全局唯一int value; //提议内容 }PROPOSAL;typedef struct ACCEPTSAL {int epoch; //流水号,1开始递增,保证全局唯一int value; //提议内容 }ACCEPTSAL; #pragma pack()enum INDEX {INIT_INDEX = 1,PREPARE_INDEX,ACCEPT_INDEX,FINISH_INDEX,ERROR_INDEX = -1, };int current_index = PREPARE_INDEX; ACCEPTSAL g_ServerRecord = {-1,-1 }; boost::asio::io_service io_service; std::mutex g_mtx; int acceptepoch = -1; //==========================================================void HandlePropose(std::shared_ptr<tcp::socket> socket) {PROPOSAL buf = { -1,-1,-1 };ACCEPTSAL tmpAcpsal = { -1,-1 };try {while (1) {boost::asio::read(*socket, boost::asio::buffer(&buf, sizeof(buf)));{std::lock_guard<std::mutex> lock(g_mtx);std::cout << "recv " << "index = " << buf.index << ". epoch = " << buf.epoch << ". value = " << buf.value << std::endl;}{std::lock_guard<std::mutex> lock(g_mtx);//prepare阶段if (buf.index == PREPARE_INDEX) {if (g_ServerRecord.epoch <= buf.epoch && g_ServerRecord.value == -1) {std::cout << "Prepare index" << std::endl;std::cout << "Prepare recv " << "index = " << buf.index << ". epoch = " << buf.epoch << ". value = " << buf.value << std::endl;//更新最新的prepare epochg_ServerRecord.epoch = buf.epoch;current_index = ACCEPT_INDEX;}}else if (buf.index == ACCEPT_INDEX && (-1 == g_ServerRecord.value)) {if ((buf.epoch >= g_ServerRecord.epoch)) {std::cout << "Accept index, epoch =" << buf.epoch << ".value = "<< buf.value << std::endl;g_ServerRecord.epoch = buf.epoch;g_ServerRecord.value = buf.value;current_index = FINISH_INDEX;}}//拷贝accepter记录tmpAcpsal = g_ServerRecord;}//回复 {std::lock_guard<std::mutex> lock(g_mtx);std::cout << "reply epoch = " << tmpAcpsal.epoch << ". value = " << tmpAcpsal.value << std::endl;}boost::asio::write(*socket, boost::asio::buffer(&tmpAcpsal, sizeof(tmpAcpsal)));}}catch (std::exception& e) {//std::cerr << e.what() << std::endl;return;} }int main() {try {tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), default_port));for (;;) {std::shared_ptr<tcp::socket> psocket = std::make_shared<tcp::socket>(io_service);acceptor.accept(*psocket);std::thread t(HandlePropose,psocket);t.detach();}}catch (std::exception& e) {std::cerr << e.what() << std::endl;}return 0; }
accepter
// Proposer.cpp: 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <ctime> #include <iostream> #include <string> #include <memory> #include <mutex> #include <random> #include <thread> #include <boost/asio.hpp>using boost::asio::ip::tcp;const std::string default_port = "9687";#pragma pack (1) //提议数据结构 typedef struct PROPOSAL {int index; //当前请求的阶段 int epoch; //流水号,1开始递增,保证全局唯一int value; //提议内容 }PROPOSAL;typedef struct ACCEPTSAL {int epoch; //流水号,1开始递增,保证全局唯一int value; //提议内容 }ACCEPTSAL; #pragma pack()enum INDEX {INIT_INDEX = 1,PREPARE_INDEX,ACCEPT_INDEX,FINISH_INDEX,ERROR_INDEX = -1, }; //======================================================== boost::asio::io_service io_service;unsigned GetRand() {static std::default_random_engine e;static std::uniform_int_distribution<unsigned> u(0, 1000);return u(e); }void ProposeThreadFunc(int id) {try {tcp::resolver resolver(io_service);tcp::resolver::query query("127.0.0.1", default_port.c_str());tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);tcp::socket socket(io_service);boost::asio::connect(socket, endpoint_iterator);int epoch = id+1;for (;;) {PROPOSAL pro = { PREPARE_INDEX ,epoch +1,id +1 };ACCEPTSAL tmpAcpsal = { -1,-1 };boost::system::error_code error;boost::asio::write(socket, boost::asio::buffer(&pro, sizeof(pro)), error);size_t len = socket.read_some(boost::asio::buffer(&tmpAcpsal, sizeof(tmpAcpsal)), error);if (error == boost::asio::error::eof)break; // Connection closed cleanly by peer.else if (error)throw boost::system::system_error(error); // Some other error.if (tmpAcpsal.epoch == pro.epoch) {pro.index = ACCEPT_INDEX;std::chrono::milliseconds dura(GetRand());std::this_thread::sleep_for(dura);boost::asio::write(socket, boost::asio::buffer(&pro, sizeof(pro)), error);size_t len = socket.read_some(boost::asio::buffer(&tmpAcpsal, sizeof(tmpAcpsal)), error);}if (tmpAcpsal.epoch > epoch) {int i = tmpAcpsal.epoch%11;int loopcount = tmpAcpsal.epoch / 11;epoch = loopcount * 11 + 11 + id + 1;if(id == 2)std::cout << "epoch = " << epoch << std::endl;}if (tmpAcpsal.value != -1) {std::cout << " value is " << tmpAcpsal.value << std::endl;break ;}std::chrono::milliseconds dura(GetRand());std::this_thread::sleep_for(dura);}}catch (std::exception& e) {std::cerr << e.what() << std::endl;} }int main() {std::thread t[11];for (int i = 0; i < 11; i++) {t[i] = std::thread(ProposeThreadFunc,i);}for (int i = 0; i < 11; i++) {t[i].join();}system("pause");return 0; }
propose
运行代码 添加随机参数 最后提交接受的数值 实现随机化
运行第一次 最后接受数值为6
运行第二次 最后接受数值为2
accept扩展多点 匹配客户端待完成
// accepters.cpp: 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <ctime> #include <iostream> #include <string> #include <memory> #include <mutex> #include <thread> #include <boost/asio.hpp>using boost::asio::ip::tcp;const int default_port = 9687;#pragma pack (1) //提议数据结构 typedef struct PROPOSAL {int index; //当前请求的阶段 int epoch; //流水号,1开始递增,保证全局唯一int value; //提议内容 }PROPOSAL;typedef struct ACCEPTSAL {int epoch; //流水号,1开始递增,保证全局唯一int value; //提议内容 }ACCEPTSAL; #pragma pack()enum INDEX {INIT_INDEX = 1,PREPARE_INDEX,ACCEPT_INDEX,FINISH_INDEX,ERROR_INDEX = -1, }; //======================================================= //多个accepter记录 boost::asio::io_service io_service;int current_index[11];// = PREPARE_INDEX; ACCEPTSAL g_ServerRecord[11];// = { -1,-1 }; std::mutex g_mtx[11]; std::mutex g_print_mtx; int acceptepoch[11];// = -1;//===================================================== void HandlePropose(std::shared_ptr<tcp::socket> socket,int id) {PROPOSAL buf = { -1,-1,-1 };ACCEPTSAL tmpAcpsal = { -1,-1 };try {while (1) {boost::asio::read(*socket, boost::asio::buffer(&buf, sizeof(buf)));{std::lock_guard<std::mutex> lock(g_mtx[id]);std::lock_guard<std::mutex> printLock(g_print_mtx);std::cout << "recv " << "index = " << buf.index << ". epoch = " << buf.epoch << ". value = " << buf.value << std::endl;}{std::lock_guard<std::mutex> lock(g_mtx[id]);//prepare阶段if (buf.index == PREPARE_INDEX) {if (g_ServerRecord[id].epoch <= buf.epoch && g_ServerRecord[id].value == -1) {{std::lock_guard<std::mutex> printLock(g_print_mtx);std::cout << "Prepare index" << std::endl;std::cout << "Prepare recv " << "index = " << buf.index << ". epoch = " << buf.epoch << ". value = " << buf.value << std::endl;}//更新最新的prepare epochg_ServerRecord[id].epoch = buf.epoch;current_index[id] = ACCEPT_INDEX;}}else if (buf.index == ACCEPT_INDEX && (-1 == g_ServerRecord[id].value)) {if ((buf.epoch >= g_ServerRecord[id].epoch)) {{std::lock_guard<std::mutex> printLock(g_print_mtx);std::cout << "Accept index, epoch =" << buf.epoch << ".value = " << buf.value << std::endl;}g_ServerRecord[id].epoch = buf.epoch;g_ServerRecord[id].value = buf.value;current_index[id] = FINISH_INDEX;}}//拷贝accepter记录tmpAcpsal = g_ServerRecord[id];}//回复 {std::lock_guard<std::mutex> lock(g_mtx[id]);{std::lock_guard<std::mutex> printLock(g_print_mtx);std::cout << "reply epoch = " << tmpAcpsal.epoch << ". value = " << tmpAcpsal.value << std::endl;}}boost::asio::write(*socket, boost::asio::buffer(&tmpAcpsal, sizeof(tmpAcpsal)));}}catch (std::exception& e) {//std::cerr << e.what() << std::endl;return;} }void AcceptThreadFunc(int id) {try {tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), default_port+id));for (;;) {std::shared_ptr<tcp::socket> psocket = std::make_shared<tcp::socket>(io_service);acceptor.accept(*psocket);std::thread t(HandlePropose, psocket,id);t.detach();}}catch (std::exception& e) {std::cerr << e.what() << std::endl;} }void init() {for (int i = 0; i < 11; i++) {current_index[i] = PREPARE_INDEX;g_ServerRecord[i].epoch = -1;g_ServerRecord[i].value = -1;} }int main() {init();std::thread t[11];for (int i = 0; i < 11; i++) {t[i] = std::thread(AcceptThreadFunc,i);}for (int i = 0; i < 11; i++) {t[i].join();}return 0; }
View Code
转载于:https://www.cnblogs.com/itdef/p/9002220.html
paxos 练手 推进中相关推荐
- c# 火狐浏览器怎么嵌入窗体中_「C#上位机必看」你们想要的练手项目来了
最近有越来越多做电气的小伙伴开始学习C#来做上位机开发,很多人在学习一段时间后,都有这种感觉,似乎学到了很多知识,但是不知道怎么应用,因此我找了一个真实的上位机小项目,让大家来练练手.这篇文章主要对这 ...
- Python练手小程序—统计英文文件中单词出现的的个数
在GitHub上发现一些很有意思的项目,由于本人作为Python的初学者,编程代码能力相对薄弱,为了加强Python的学习,特此利用前辈们的学习知识成果,自己去亲自实现. 一周没有更新了,主要还是自己 ...
- 一个适合于Python 初学者的入门练手项目
随着人工智能的兴起,国内掀起了一股Python学习热潮,入门级编程语言,大多选择Python,有经验的程序员,也开始学习Python,正所谓是人生苦短,我用Python 有个Python入门练手项目, ...
- python新手项目-推荐:一个适合于Python新手的入门练手项目
原标题:推荐:一个适合于Python新手的入门练手项目 随着人工智能的兴起,国内掀起了一股Python学习热潮,入门级编程语言,大多选择Python,有经验的程序员,也开始学习Python,正所谓是人 ...
- python新手小项目-推荐:一个适合于Python新手的入门练手项目
随着人工智能的兴起,国内掀起了一股Python学习热潮,入门级编程语言,大多选择Python,有经验的程序员,也开始学习Python,正所谓是人生苦短,我用Python 有个Python入门练手项目, ...
- python新手程序_推荐:一个适合于Python新手的入门练手项目
随着人工智能的兴起,国内掀起了一股Python学习热潮,入门级编程语言,大多选择Python,有经验的程序员,也开始学习Python,正所谓是人生苦短,我用Python 有个Python入门练手项目, ...
- python新手入门项目推荐_推荐:一个适合于Python新手的入门练手项目
随着人工智能的兴起,国内掀起了一股Python学习热潮,入门级编程语言,大多选择Python,有经验的程序员,也开始学习Python,正所谓是人生苦短,我用Python 有个Python入门练手项目, ...
- 适合新手入门的8个python项目_推荐:一个适合于Python新手的入门练手项目
随着人工智能的兴起,国内掀起了一股Python学习热潮,入门级编程语言,大多选择Python,有经验的程序员,也开始学习Python,正所谓是人生苦短,我用Python 有个Python入门练手项目, ...
- 一个适合于Python初学者的入门练手项目
随着人工智能的兴起,国内掀起了一股Python学习热潮,入门级编程语言,大多选择Python,有经验的程序员,也开始学习Python,正所谓是人生苦短,我用Python 有个Python入门练手项目, ...
最新文章
- 英语是缺乏AOP的语言,汉语是具备AOP的语言。
- java中的IO详解(上)
- 【 HDU1043-经典BFS+康拓展开 八数码】 (待更)
- 23种设计模式C++源码与UML实现--工厂模式
- python程序设计案例课堂第二篇_Python程序设计案例课堂第二篇核心技术第十章图形用户界面...
- LiveVideoStack线上交流分享 ( 五 ) —— 在线教育音视频技术探索与应用
- iPhone清理喇叭灰尘_厉害了,iPhone 专用的网购商品历史最低价查询工具
- linux io分析工具,io性能分析工具-iostat
- 学习C++项目—— 搭建多进程网络服务框架,增加业务和日志,心跳机制
- 【生信进阶练习1000days】day13-GEOquery
- 我是如何入门机器学习的呢
- yuv420p 详解_YUV格式详解,图文详解YUV420数据格式
- 数字金额转化为中文大写
- self._handle = _dlopen(self._name, mode) OSError: [WinError 126] 找不到指定的模块
- Linux各目录及每个目录的详细介绍
- springboot中如何使用RedisTemplate存储实体对象
- 分形几何python代码_Python教程之绘制Mandelbrot集合
- 如何破解网络密码?(2种方法)
- 云计算:优势与未来趋势
- PCL(Point Cloud Library)的第三方库简介(boost,eigen,flann,vtk,qhull)
热门文章
- Web前端开发:SQL Jsp小项目(一)
- 转:ubuntu或linux网卡配置/etc/network/interfaces
- C++ 工程实践(2):不要重载全局 ::operator new()
- 地平线开源轻量级、有效可变组卷积的人脸识别网络VarGFaceNet
- 深度学习超分辨率最新综述:一文道尽技术分类与效果评测
- html中文案竖排怎么写,做了这个活动,感觉自己成了垂直排版css大师(文字竖排)...
- 大数据分析必须要会的数据预处理操作(一)!!!
- numpy.random随机数模块常用函数总结
- 从大数据到深度学习,这些年度开源“新秀”你可用过?
- mscoco数据集_caffe详解之数据层