2016-03-14 11:16:40 +03:00
|
|
|
|
#include <iostream>
|
2016-02-20 13:40:58 +03:00
|
|
|
|
#include <thread>
|
2016-02-23 09:26:05 +03:00
|
|
|
|
#include <random>
|
|
|
|
|
#include <chrono>
|
2016-03-15 01:14:20 +03:00
|
|
|
|
#include <ctime>
|
2016-02-02 15:40:07 +03:00
|
|
|
|
|
2016-02-29 09:27:59 +03:00
|
|
|
|
#include <mpi.h>
|
|
|
|
|
|
2016-02-03 14:26:01 +03:00
|
|
|
|
#include <multiverso/multiverso.h>
|
2016-02-19 05:46:07 +03:00
|
|
|
|
#include <multiverso/net.h>
|
2016-02-04 06:03:53 +03:00
|
|
|
|
#include <multiverso/util/log.h>
|
2016-02-19 05:46:07 +03:00
|
|
|
|
#include <multiverso/util/net_util.h>
|
2016-04-17 14:56:58 +03:00
|
|
|
|
#include <multiverso/util/configure.h>
|
2016-04-19 12:25:20 +03:00
|
|
|
|
#include <multiverso/util/timer.h>
|
2016-04-19 18:30:18 +03:00
|
|
|
|
#include <multiverso/dashboard.h>
|
2016-02-02 15:40:07 +03:00
|
|
|
|
|
2016-02-03 14:26:01 +03:00
|
|
|
|
#include <multiverso/table/array_table.h>
|
|
|
|
|
#include <multiverso/table/kv_table.h>
|
2016-03-30 08:40:20 +03:00
|
|
|
|
#include <multiverso/table/matrix_table.h>
|
2016-04-19 12:25:20 +03:00
|
|
|
|
#include <multiverso/table/sparse_matrix_table.h>
|
2016-04-07 15:05:32 +03:00
|
|
|
|
#include <multiverso/updater/updater.h>
|
2016-03-03 09:11:04 +03:00
|
|
|
|
|
2016-03-31 12:37:34 +03:00
|
|
|
|
#include <gtest/gtest.h>
|
2016-04-19 12:25:20 +03:00
|
|
|
|
#include <memory>
|
2016-03-14 08:32:06 +03:00
|
|
|
|
|
2016-02-02 15:40:07 +03:00
|
|
|
|
using namespace multiverso;
|
|
|
|
|
|
2016-02-19 16:11:20 +03:00
|
|
|
|
void TestKV(int argc, char* argv[]) {
|
2016-02-02 15:40:07 +03:00
|
|
|
|
Log::Info("Test KV map \n");
|
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
|
// this is a demo of distributed hash table to show how to use the multiverso
|
|
|
|
|
// ----------------------------------------------------------------------- //
|
|
|
|
|
|
|
|
|
|
// 1. Start the Multiverso engine ---------------------------------------- //
|
2016-03-01 06:34:23 +03:00
|
|
|
|
MV_Init(&argc, argv);
|
2016-02-02 15:40:07 +03:00
|
|
|
|
|
|
|
|
|
// 2. To create the shared table ----------------------------------------- //
|
|
|
|
|
|
|
|
|
|
// TODO(feiga): This table must be create at both worker and server endpoint
|
|
|
|
|
// simultaneously, since they should share same type and same created order
|
|
|
|
|
// (same order means same table id). So it's better to create them with some
|
|
|
|
|
// specific creator, instead of current way
|
|
|
|
|
|
|
|
|
|
// TODO(feiga): should add some if statesment
|
|
|
|
|
// if the node is worker, then create a worker cache table
|
|
|
|
|
KVWorkerTable<int, int>* dht = new KVWorkerTable<int, int>();
|
|
|
|
|
// if the node is server, then create a server storage table
|
|
|
|
|
KVServerTable<int, int>* server_dht = new KVServerTable<int, int>();
|
|
|
|
|
|
2016-03-01 06:34:23 +03:00
|
|
|
|
MV_Barrier();
|
2016-02-02 15:40:07 +03:00
|
|
|
|
|
|
|
|
|
// 3. User program ------------------------------------------------------- //
|
|
|
|
|
|
|
|
|
|
// all this interface is related with the KVWorkerTable
|
|
|
|
|
// the data structure and the interface can be both defined by users
|
|
|
|
|
// We also provides several common implementations
|
|
|
|
|
// For specific program, user-defined table may provides better performance
|
|
|
|
|
|
|
|
|
|
// access the local cache
|
|
|
|
|
std::unordered_map<int, int>& kv = dht->raw();
|
|
|
|
|
|
|
|
|
|
// The Get/Add are sync operation, when the function call returns, we already
|
|
|
|
|
// Get from server, or the server has Added the update
|
|
|
|
|
|
|
|
|
|
// Get from the server
|
|
|
|
|
dht->Get(0);
|
|
|
|
|
// Check the result. Since no one added, this should be 0
|
2016-03-04 09:18:15 +03:00
|
|
|
|
Log::Info("Get 0 from kv server: result = %d\n", kv[0]);
|
2016-02-02 15:40:07 +03:00
|
|
|
|
|
|
|
|
|
// Add 1 to the server
|
2016-03-04 09:18:15 +03:00
|
|
|
|
dht->Add(0, 1);
|
2016-02-02 15:40:07 +03:00
|
|
|
|
|
|
|
|
|
// Check the result. Since just added one, this should be 1
|
|
|
|
|
dht->Get(0);
|
|
|
|
|
|
|
|
|
|
Log::Info("Get 0 from kv server after add 1: result = %d\n", kv[0]);
|
|
|
|
|
|
|
|
|
|
// 4. Shutdown the Multiverso engine. ------------------------------------ //
|
2016-03-01 06:34:23 +03:00
|
|
|
|
MV_ShutDown();
|
2016-02-02 15:40:07 +03:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-19 16:11:20 +03:00
|
|
|
|
void TestArray(int argc, char* argv[]) {
|
2016-02-02 15:40:07 +03:00
|
|
|
|
Log::Info("Test Array \n");
|
|
|
|
|
|
2016-03-01 06:34:23 +03:00
|
|
|
|
MV_Init(&argc, argv);
|
2016-03-28 05:42:10 +03:00
|
|
|
|
|
2016-02-24 13:58:37 +03:00
|
|
|
|
ArrayWorker<float>* shared_array = new ArrayWorker<float>(1000000);
|
|
|
|
|
ArrayServer<float>* server_array = new ArrayServer<float>(1000000);
|
2016-02-02 15:40:07 +03:00
|
|
|
|
|
2016-03-01 06:34:23 +03:00
|
|
|
|
MV_Barrier();
|
2016-02-02 15:40:07 +03:00
|
|
|
|
Log::Info("Create tables OK\n");
|
|
|
|
|
|
2016-02-23 09:15:22 +03:00
|
|
|
|
int iter = 1000;
|
2016-03-28 05:42:10 +03:00
|
|
|
|
|
2016-04-07 15:05:32 +03:00
|
|
|
|
if (argc == 2) iter = atoi(argv[1]);
|
2016-02-23 09:15:22 +03:00
|
|
|
|
|
|
|
|
|
for (int i = 0; i < iter; ++i) {
|
2016-03-28 05:42:10 +03:00
|
|
|
|
// std::vector<float>& vec = shared_array->raw();
|
2016-02-02 15:40:07 +03:00
|
|
|
|
|
2016-03-28 05:42:10 +03:00
|
|
|
|
// shared_array->Get();
|
2016-02-24 13:58:37 +03:00
|
|
|
|
float* data = new float[1000000];
|
2016-04-18 16:57:39 +03:00
|
|
|
|
shared_array->Get(data, 1000000);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 10; ++i)
|
|
|
|
|
std::cout << data[i] << " "; std::cout << std::endl;
|
2016-02-02 15:40:07 +03:00
|
|
|
|
|
2016-02-24 13:58:37 +03:00
|
|
|
|
std::vector<float> delta(1000000);
|
2016-03-28 05:42:10 +03:00
|
|
|
|
for (int i = 0; i < 1000000; ++i)
|
2016-02-18 15:42:07 +03:00
|
|
|
|
delta[i] = static_cast<float>(i);
|
2016-02-02 15:40:07 +03:00
|
|
|
|
|
2016-04-07 13:42:52 +03:00
|
|
|
|
UpdateOption option;
|
|
|
|
|
option.set_learning_rate(1 - 0.0001 * i);
|
|
|
|
|
option.set_momentum(0.99);
|
2016-04-13 11:18:50 +03:00
|
|
|
|
option.set_rho(0.01f);
|
2016-04-07 13:42:52 +03:00
|
|
|
|
shared_array->Add(delta.data(), 1000000, &option);
|
2016-04-18 16:57:39 +03:00
|
|
|
|
shared_array->Add(delta.data(), 1000000, &option);
|
2016-02-02 15:40:07 +03:00
|
|
|
|
|
2016-02-18 15:42:07 +03:00
|
|
|
|
}
|
2016-03-01 06:34:23 +03:00
|
|
|
|
MV_ShutDown();
|
2016-02-02 15:40:07 +03:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-19 11:07:49 +03:00
|
|
|
|
|
2016-02-23 17:46:05 +03:00
|
|
|
|
#define ARRAY_SIZE 4683776
|
2016-02-20 13:40:58 +03:00
|
|
|
|
void TestMultipleThread(int argc, char* argv[])
|
|
|
|
|
{
|
2016-04-17 14:56:58 +03:00
|
|
|
|
Log::Info("Test Multiple threads \n");
|
|
|
|
|
std::mt19937_64 eng{ std::random_device{}() };
|
|
|
|
|
std::uniform_int_distribution<> dist{ 5, 10000 };
|
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds{ dist(eng) });
|
|
|
|
|
//Log::ResetLogLevel(LogLevel::Debug);
|
|
|
|
|
MV_Init(&argc, argv);
|
|
|
|
|
|
|
|
|
|
ArrayWorker<float>* shared_array = new ArrayWorker<float>(ARRAY_SIZE);
|
|
|
|
|
ArrayServer<float>* server_array = new ArrayServer<float>(ARRAY_SIZE);
|
|
|
|
|
std::thread* m_prefetchThread = nullptr;
|
|
|
|
|
MV_Barrier();
|
|
|
|
|
Log::Info("Create tables OK\n");
|
|
|
|
|
|
|
|
|
|
std::vector<float> delta(ARRAY_SIZE);
|
|
|
|
|
while (true){
|
|
|
|
|
if (m_prefetchThread != nullptr && m_prefetchThread->joinable())
|
|
|
|
|
{
|
|
|
|
|
m_prefetchThread->join();
|
|
|
|
|
delete m_prefetchThread;
|
|
|
|
|
m_prefetchThread = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::fill(delta.begin(), delta.end(), 0);
|
|
|
|
|
for (int i = 0; i < ARRAY_SIZE; ++i)
|
|
|
|
|
{
|
|
|
|
|
std::mt19937_64 eng{ std::random_device{}() };
|
|
|
|
|
std::uniform_real_distribution<float> dist{ -1, 1 };
|
|
|
|
|
delta[i] = dist(eng);
|
|
|
|
|
}
|
|
|
|
|
m_prefetchThread = new std::thread([&](){
|
|
|
|
|
|
|
|
|
|
shared_array->Add(delta.data(), ARRAY_SIZE);
|
|
|
|
|
shared_array->Get(delta.data(), ARRAY_SIZE);
|
|
|
|
|
Log::Info("Rank %d Get OK\n", MV_Rank());
|
|
|
|
|
for (int i = 0; i < 10; ++i)
|
|
|
|
|
std::cout << delta[i] << " "; std::cout << std::endl;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
MV_Barrier();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
MV_ShutDown();
|
2016-02-20 13:40:58 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-02-19 16:11:20 +03:00
|
|
|
|
void TestNet(int argc, char* argv[]) {
|
2016-02-02 15:40:07 +03:00
|
|
|
|
NetInterface* net = NetInterface::Get();
|
2016-02-19 16:11:20 +03:00
|
|
|
|
net->Init(&argc, argv);
|
2016-02-02 15:40:07 +03:00
|
|
|
|
|
2016-03-02 11:02:03 +03:00
|
|
|
|
const char* chi1 = std::string("hello, world").c_str();
|
|
|
|
|
const char* chi2 = std::string("hello, c++").c_str();
|
|
|
|
|
const char* chi3 = std::string("hello, multiverso").c_str();
|
|
|
|
|
char* hi1 = new char[14];
|
|
|
|
|
strcpy(hi1, chi1);
|
|
|
|
|
char* hi2 = new char[12];
|
|
|
|
|
strcpy(hi2, chi2);
|
|
|
|
|
char* hi3 = new char[19];
|
|
|
|
|
strcpy(hi3, chi3);
|
2016-02-02 15:40:07 +03:00
|
|
|
|
if (net->rank() == 0) {
|
2016-03-01 17:51:27 +03:00
|
|
|
|
for (int rank = 1; rank < net->size(); ++rank) {
|
2016-03-03 05:41:59 +03:00
|
|
|
|
MessagePtr msg(new Message());// = std::make_unique<Message>();
|
|
|
|
|
msg->set_src(0);
|
|
|
|
|
msg->set_dst(rank);
|
|
|
|
|
msg->Push(Blob(hi1, 13));
|
|
|
|
|
msg->Push(Blob(hi2, 11));
|
|
|
|
|
msg->Push(Blob(hi3, 18));
|
2016-03-08 22:31:22 +03:00
|
|
|
|
for (int i = 0; i < msg->size(); ++i) {
|
|
|
|
|
Log::Info("In Send: %s\n", msg->data()[i].data());
|
|
|
|
|
};
|
2016-04-17 14:56:58 +03:00
|
|
|
|
while (net->Send(msg) == 0);
|
2016-03-03 05:41:59 +03:00
|
|
|
|
Log::Info("rank 0 send\n");
|
2016-03-01 17:51:27 +03:00
|
|
|
|
}
|
2016-02-23 09:15:22 +03:00
|
|
|
|
|
2016-03-01 17:51:27 +03:00
|
|
|
|
for (int i = 1; i < net->size(); ++i) {
|
|
|
|
|
MessagePtr msg(new Message());
|
|
|
|
|
msg.reset(new Message());
|
|
|
|
|
while (net->Recv(&msg) == 0) {
|
|
|
|
|
// Log::Info("recv return 0\n");
|
|
|
|
|
}
|
|
|
|
|
Log::Info("rank 0 recv\n");
|
|
|
|
|
// CHECK(strcmp(msg->data()[0].data(), hi) == 0);
|
|
|
|
|
std::vector<Blob> recv_data = msg->data();
|
|
|
|
|
CHECK(recv_data.size() == 3);
|
|
|
|
|
for (int i = 0; i < msg->size(); ++i) {
|
|
|
|
|
Log::Info("recv from srv %d: %s\n", msg->src(), recv_data[i].data());
|
|
|
|
|
};
|
2016-02-23 09:15:22 +03:00
|
|
|
|
}
|
2016-04-17 14:56:58 +03:00
|
|
|
|
}
|
|
|
|
|
else {// other rank
|
2016-02-26 09:36:38 +03:00
|
|
|
|
MessagePtr msg(new Message());// = std::make_unique<Message>();
|
2016-02-23 09:15:22 +03:00
|
|
|
|
while (net->Recv(&msg) == 0) {
|
2016-03-01 17:51:27 +03:00
|
|
|
|
// Log::Info("recv return 0\n");
|
2016-02-23 09:15:22 +03:00
|
|
|
|
}
|
2016-03-01 17:51:27 +03:00
|
|
|
|
Log::Info("rank %d recv\n", net->rank());
|
|
|
|
|
std::vector<Blob>& recv_data = msg->data();
|
2016-02-19 16:11:20 +03:00
|
|
|
|
CHECK(recv_data.size() == 3);
|
|
|
|
|
for (int i = 0; i < msg->size(); ++i) {
|
|
|
|
|
Log::Info("%s\n", recv_data[i].data());
|
|
|
|
|
}
|
2016-02-23 09:15:22 +03:00
|
|
|
|
|
|
|
|
|
msg.reset(new Message());
|
2016-03-01 17:51:27 +03:00
|
|
|
|
msg->set_src(net->rank());
|
2016-02-23 09:15:22 +03:00
|
|
|
|
msg->set_dst(0);
|
|
|
|
|
msg->Push(Blob(hi1, 13));
|
|
|
|
|
msg->Push(Blob(hi2, 11));
|
|
|
|
|
msg->Push(Blob(hi3, 18));
|
2016-04-17 14:56:58 +03:00
|
|
|
|
while (net->Send(msg) == 0);
|
2016-03-01 17:51:27 +03:00
|
|
|
|
Log::Info("rank %d send\n", net->rank());
|
2016-02-02 15:40:07 +03:00
|
|
|
|
}
|
2016-03-01 17:51:27 +03:00
|
|
|
|
// while (!net->Test()) {
|
|
|
|
|
// // wait all message process finished
|
|
|
|
|
// }
|
2016-02-02 15:40:07 +03:00
|
|
|
|
|
|
|
|
|
net->Finalize();
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-19 05:46:07 +03:00
|
|
|
|
void TestIP() {
|
2016-02-19 07:01:26 +03:00
|
|
|
|
std::unordered_set<std::string> ip_list;
|
2016-02-26 09:36:38 +03:00
|
|
|
|
// net::GetLocalIPAddress(&ip_list);
|
|
|
|
|
for (auto ip : ip_list) Log::Info("%s\n", ip.c_str());
|
2016-02-19 05:46:07 +03:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-17 14:56:58 +03:00
|
|
|
|
void TestNoNet(int argc, char* argv[]) {
|
2016-02-29 09:27:59 +03:00
|
|
|
|
int provided;
|
|
|
|
|
MPI_Init_thread(&argc, &argv, MPI_THREAD_SERIALIZED, &provided);
|
|
|
|
|
|
|
|
|
|
MPI_Barrier(MPI_COMM_WORLD);
|
2016-03-01 06:34:23 +03:00
|
|
|
|
MV_Init(&argc, argv);
|
2016-02-29 09:27:59 +03:00
|
|
|
|
|
|
|
|
|
ArrayWorker<float>* shared_array = new ArrayWorker<float>(ARRAY_SIZE);
|
|
|
|
|
ArrayServer<float>* server_array = new ArrayServer<float>(ARRAY_SIZE);
|
|
|
|
|
std::thread* m_prefetchThread = nullptr;
|
2016-03-01 06:34:23 +03:00
|
|
|
|
MV_Barrier();
|
2016-02-29 09:27:59 +03:00
|
|
|
|
Log::Info("Create tables OK\n");
|
|
|
|
|
|
|
|
|
|
std::vector<float> delta(ARRAY_SIZE);
|
|
|
|
|
while (true){
|
|
|
|
|
if (m_prefetchThread != nullptr && m_prefetchThread->joinable())
|
|
|
|
|
{
|
|
|
|
|
m_prefetchThread->join();
|
|
|
|
|
delete m_prefetchThread;
|
|
|
|
|
m_prefetchThread = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::fill(delta.begin(), delta.end(), 0);
|
|
|
|
|
for (int i = 0; i < ARRAY_SIZE; ++i)
|
|
|
|
|
{
|
|
|
|
|
std::mt19937_64 eng{ std::random_device{}() };
|
|
|
|
|
std::uniform_real_distribution<float> dist{ -1, 1 };
|
|
|
|
|
delta[i] = dist(eng);
|
|
|
|
|
}
|
|
|
|
|
m_prefetchThread = new std::thread([&](){
|
|
|
|
|
|
|
|
|
|
shared_array->Add(delta.data(), ARRAY_SIZE);
|
|
|
|
|
shared_array->Get(delta.data(), ARRAY_SIZE);
|
2016-03-01 06:34:23 +03:00
|
|
|
|
Log::Info("Rank %d Get OK\n", MV_Rank());
|
2016-02-29 09:27:59 +03:00
|
|
|
|
for (int i = 0; i < 10; ++i)
|
|
|
|
|
std::cout << delta[i] << " "; std::cout << std::endl;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
//shared_array->Get(data, 10);
|
2016-03-01 06:34:23 +03:00
|
|
|
|
MV_Barrier();
|
2016-02-29 09:27:59 +03:00
|
|
|
|
|
|
|
|
|
}
|
2016-03-01 06:34:23 +03:00
|
|
|
|
MV_ShutDown();
|
2016-03-01 17:51:27 +03:00
|
|
|
|
}
|
|
|
|
|
|
2016-03-03 11:30:09 +03:00
|
|
|
|
void TestMatrix(int argc, char* argv[]){
|
2016-04-17 14:56:58 +03:00
|
|
|
|
Log::Info("Test Matrix\n");
|
2016-03-03 11:30:09 +03:00
|
|
|
|
|
2016-04-17 14:56:58 +03:00
|
|
|
|
MV_Init(&argc, argv);
|
2016-03-03 11:30:09 +03:00
|
|
|
|
|
2016-04-17 14:56:58 +03:00
|
|
|
|
int num_row = 11, num_col = 10;
|
|
|
|
|
int size = num_row * num_col;
|
2016-03-03 11:30:09 +03:00
|
|
|
|
|
2016-03-28 05:42:10 +03:00
|
|
|
|
// MatrixWorkerTable<int>* worker_table =
|
2016-04-17 14:56:58 +03:00
|
|
|
|
// static_cast<MatrixWorkerTable<int>*>(MV_CreateTable<int>("matrix", { &num_row, &num_col })); //new implementation
|
2016-03-28 05:42:10 +03:00
|
|
|
|
// static_cast<MatrixWorkerTable<int>*>((new MatrixTableHelper<int>(num_row, num_col))->CreateTable()); //older one
|
2016-03-22 06:28:48 +03:00
|
|
|
|
|
2016-03-28 05:42:10 +03:00
|
|
|
|
//if (worker_table == nullptr){ //should have more if statement to avoid nullptr in using worker_table
|
|
|
|
|
// Log::Debug("rank %d has no worker\n", MV_Rank());
|
|
|
|
|
// }
|
2016-03-03 11:30:09 +03:00
|
|
|
|
|
2016-04-17 14:56:58 +03:00
|
|
|
|
MatrixWorkerTable<float>* worker_table = new MatrixWorkerTable<float>(num_row, num_col);
|
|
|
|
|
MatrixServerTable<float>* server_table = new MatrixServerTable<float>(num_row, num_col);
|
|
|
|
|
std::thread* m_prefetchThread = nullptr;
|
|
|
|
|
MV_Barrier();
|
|
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
if (m_prefetchThread != nullptr && m_prefetchThread->joinable())
|
|
|
|
|
{
|
|
|
|
|
m_prefetchThread->join();
|
|
|
|
|
delete m_prefetchThread;
|
|
|
|
|
m_prefetchThread = nullptr;
|
|
|
|
|
}
|
|
|
|
|
std::vector<int> v = { 0, 1, 5, 10 };
|
|
|
|
|
|
|
|
|
|
// test data
|
|
|
|
|
std::vector<float> delta(size);
|
|
|
|
|
for (int i = 0; i < size; ++i)
|
|
|
|
|
delta[i] = i;
|
|
|
|
|
|
|
|
|
|
float * data = new float[size];
|
|
|
|
|
m_prefetchThread = new std::thread([&](){
|
2016-03-03 11:30:09 +03:00
|
|
|
|
|
2016-04-13 11:18:50 +03:00
|
|
|
|
UpdateOption option;
|
2016-04-17 14:56:58 +03:00
|
|
|
|
worker_table->Add(delta.data(), size, &option); //add all
|
|
|
|
|
|
|
|
|
|
worker_table->Get(data, size); //get all
|
|
|
|
|
printf("----------------------------\n");
|
|
|
|
|
for (int i = 0; i < num_row; ++i){
|
|
|
|
|
printf("rank %d, row %d: ", MV_Rank(), i);
|
|
|
|
|
for (int j = 0; j < num_col; ++j)
|
|
|
|
|
printf("%.2f ", data[i * num_col + j]);
|
|
|
|
|
printf("\n");
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
MV_Barrier();
|
|
|
|
|
if (m_prefetchThread != nullptr && m_prefetchThread->joinable())
|
|
|
|
|
{
|
|
|
|
|
m_prefetchThread->join();
|
|
|
|
|
delete m_prefetchThread;
|
|
|
|
|
m_prefetchThread = nullptr;
|
|
|
|
|
}
|
|
|
|
|
//test data_vec
|
|
|
|
|
std::vector<float*> data_rows = { &data[0], &data[num_col], &data[5 * num_col], &data[10 * num_col] };
|
|
|
|
|
std::vector<float*> delta_rows = { &delta[0], &delta[num_col], &delta[5 * num_col], &delta[10 * num_col] };
|
2016-04-13 11:18:50 +03:00
|
|
|
|
UpdateOption option;
|
2016-04-17 14:56:58 +03:00
|
|
|
|
worker_table->Add(v, delta_rows, num_col, &option);
|
|
|
|
|
worker_table->Get(v, data_rows, num_col);
|
|
|
|
|
MV_Barrier();
|
|
|
|
|
|
|
|
|
|
printf("----------------------------\n");
|
|
|
|
|
for (int i = 0; i < num_row; ++i){
|
|
|
|
|
printf("rank %d, row %d: ", MV_Rank(), i);
|
|
|
|
|
for (int j = 0; j < num_col; ++j)
|
|
|
|
|
printf("%.2f ", data[i * num_col + j]);
|
|
|
|
|
printf("\n");
|
|
|
|
|
}
|
|
|
|
|
MV_Barrier();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
MV_ShutDown();
|
2016-03-03 11:30:09 +03:00
|
|
|
|
}
|
|
|
|
|
|
2016-03-09 09:10:53 +03:00
|
|
|
|
void TestCheckPoint(int argc, char* argv[], bool restore){
|
|
|
|
|
Log::Info("Test CheckPoint\n");
|
|
|
|
|
|
2016-04-17 14:56:58 +03:00
|
|
|
|
MV_Init(&argc, argv);
|
2016-03-09 09:10:53 +03:00
|
|
|
|
|
|
|
|
|
int num_row = 11, num_col = 10;
|
|
|
|
|
int size = num_row * num_col;
|
|
|
|
|
|
2016-03-14 11:16:40 +03:00
|
|
|
|
MatrixWorkerTable<int>* worker_table =
|
2016-03-22 06:28:48 +03:00
|
|
|
|
static_cast<MatrixWorkerTable<int>*>((new MatrixTableHelper<int>(num_row, num_col))->CreateTable());
|
2016-03-14 11:16:40 +03:00
|
|
|
|
//MatrixWorkerTable<int>* worker_table = new MatrixWorkerTable<int>(num_row, num_col);
|
|
|
|
|
//MatrixServerTable<int>* server_table = new MatrixServerTable<int>(num_row, num_col);
|
2016-03-09 09:10:53 +03:00
|
|
|
|
//if restore = true, will restore server data and return the next iter number of last dump file
|
|
|
|
|
//else do nothing and return 0
|
2016-03-15 11:18:05 +03:00
|
|
|
|
if (worker_table == nullptr) {
|
|
|
|
|
//no worker in this node
|
|
|
|
|
}
|
2016-03-28 05:42:10 +03:00
|
|
|
|
// int begin_iter = MV_LoadTable("serverTable_");
|
2016-03-09 09:10:53 +03:00
|
|
|
|
MV_Barrier();//won't dump data without parameters
|
|
|
|
|
|
|
|
|
|
std::vector<int> delta(size);
|
|
|
|
|
for (int i = 0; i < size; ++i)
|
|
|
|
|
delta[i] = i;
|
|
|
|
|
int * data = new int[size];
|
|
|
|
|
|
2016-03-28 05:42:10 +03:00
|
|
|
|
// Log::Debug("rank %d start from iteration %d\n", MV_Rank(), begin_iter);
|
2016-03-09 09:10:53 +03:00
|
|
|
|
|
2016-03-28 05:42:10 +03:00
|
|
|
|
for (int i = 0 /*begin_iter*/; i < 50; ++i){
|
2016-03-09 09:10:53 +03:00
|
|
|
|
worker_table->Add(delta.data(), size);
|
2016-03-28 05:42:10 +03:00
|
|
|
|
MV_Barrier(); //dump table data with iteration i each k iterations
|
2016-03-09 09:10:53 +03:00
|
|
|
|
}
|
|
|
|
|
worker_table->Get(data, size);
|
|
|
|
|
|
|
|
|
|
printf("----------------------------\n");
|
|
|
|
|
for (int i = 0; i < num_row; ++i){
|
|
|
|
|
printf("rank %d, row %d: ", MV_Rank(), i);
|
|
|
|
|
for (int j = 0; j < num_col; ++j)
|
|
|
|
|
printf("%d ", data[i * num_col + j]);
|
|
|
|
|
printf("\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MV_ShutDown();
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-17 14:56:58 +03:00
|
|
|
|
void TestAllreduce(int argc, char* argv[]) {
|
2016-04-17 15:34:23 +03:00
|
|
|
|
multiverso::SetCMDFlag("ma", true);
|
2016-04-17 14:56:58 +03:00
|
|
|
|
MV_Init(&argc, argv);
|
|
|
|
|
int a = 1;
|
|
|
|
|
MV_Aggregate(&a, 1);
|
|
|
|
|
std::cout << "a = " << a << std::endl;
|
|
|
|
|
MV_ShutDown();
|
2016-02-29 09:27:59 +03:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-19 12:25:20 +03:00
|
|
|
|
void TestSparseMatrixTable(int argc, char* argv[]) {
|
|
|
|
|
Log::ResetLogLevel(LogLevel::Error);
|
|
|
|
|
Log::Info("Test Sparse Matrix\n");
|
|
|
|
|
Timer timmer;
|
|
|
|
|
|
|
|
|
|
MV_Init(&argc, argv);
|
|
|
|
|
|
|
|
|
|
int num_row = 100000, num_col = 50;
|
|
|
|
|
int size = num_row * num_col;
|
|
|
|
|
int worker_id = MV_Rank();
|
|
|
|
|
|
|
|
|
|
// test data
|
|
|
|
|
int* data = new int[size];
|
|
|
|
|
int* delta = new int[size];
|
|
|
|
|
int* keys = new int[num_row];
|
|
|
|
|
for (auto i = 0; i < size; ++i) {
|
|
|
|
|
delta[i] = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UpdateOption option;
|
|
|
|
|
option.set_worker_id(worker_id);
|
|
|
|
|
|
2016-04-19 18:30:18 +03:00
|
|
|
|
std::cout << "==> test get twice, the second get should be shorter than the first one." << std::endl;
|
2016-04-19 12:25:20 +03:00
|
|
|
|
{
|
|
|
|
|
auto worker_table = std::shared_ptr<SparseMatrixWorkerTable<int>>(
|
|
|
|
|
new SparseMatrixWorkerTable<int>(num_row, num_col));
|
|
|
|
|
auto server_table = std::shared_ptr<SparseMatrixServerTable<int>>(
|
|
|
|
|
new SparseMatrixServerTable<int>(num_row, num_col, false));
|
|
|
|
|
MV_Barrier();
|
|
|
|
|
|
|
|
|
|
|
2016-04-19 18:30:18 +03:00
|
|
|
|
timmer.Start();
|
2016-04-19 12:25:20 +03:00
|
|
|
|
worker_table->Get(data, size, worker_id);
|
|
|
|
|
std::cout << " " << timmer.elapse() << "s:\t" << "get all rows 1st time" << std::endl;
|
|
|
|
|
|
|
|
|
|
// do not need to get any rows, since all rows are up-to-date
|
2016-04-19 18:30:18 +03:00
|
|
|
|
timmer.Start();
|
2016-04-19 12:25:20 +03:00
|
|
|
|
worker_table->Get(data, size, worker_id);
|
|
|
|
|
std::cout << " " << timmer.elapse() << "s:\t" << "get all rows 2nd time" << std::endl;
|
|
|
|
|
|
|
|
|
|
for (auto i = 0; i < size; ++i) {
|
|
|
|
|
ASSERT_EQ(0, data[i]) << "Should be inited as 0";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::cout << "==> test add to all rows" << std::endl;
|
|
|
|
|
{
|
|
|
|
|
auto worker_table = std::shared_ptr<SparseMatrixWorkerTable<int>>(
|
|
|
|
|
new SparseMatrixWorkerTable<int>(num_row, num_col));
|
|
|
|
|
auto server_table = std::shared_ptr<SparseMatrixServerTable<int>>(
|
|
|
|
|
new SparseMatrixServerTable<int>(num_row, num_col, false));
|
2016-04-19 18:30:18 +03:00
|
|
|
|
timmer.Start();
|
2016-04-19 12:25:20 +03:00
|
|
|
|
worker_table->Add(delta, size, &option);
|
|
|
|
|
worker_table->Get(data, size, -1);
|
|
|
|
|
std::cout << " " << timmer.elapse() << "s:\t" << "add 1 to all values, and get all rows after adding" << std::endl;
|
|
|
|
|
for (auto i = 0; i < size; ++i) {
|
|
|
|
|
ASSERT_EQ(1, data[i]) << "Should be 1 after adding";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MV_Barrier();
|
|
|
|
|
MV_ShutDown();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void TestMatrixPerformance(int argc, char* argv[], bool sparse) {
|
2016-04-20 13:10:21 +03:00
|
|
|
|
Log::ResetLogLevel(LogLevel::Error);
|
2016-04-19 12:25:20 +03:00
|
|
|
|
Log::Info("Test Sparse Matrix\n");
|
|
|
|
|
Timer timmer;
|
|
|
|
|
|
|
|
|
|
MV_Init(&argc, argv);
|
|
|
|
|
|
|
|
|
|
int num_row = 100000, num_col = 50;
|
|
|
|
|
int size = num_row * num_col;
|
|
|
|
|
int worker_id = MV_Rank();
|
|
|
|
|
|
|
|
|
|
// test data
|
|
|
|
|
int* data = new int[size];
|
|
|
|
|
int* delta = new int[size];
|
|
|
|
|
int* keys = new int[num_row];
|
2016-04-20 16:45:58 +03:00
|
|
|
|
for (auto row = 0; row < num_row; ++row) {
|
|
|
|
|
for (auto col = 0; col < num_col; ++col) {
|
|
|
|
|
delta[row * num_col + col] = row + 2;
|
|
|
|
|
}
|
2016-04-19 12:25:20 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UpdateOption option;
|
|
|
|
|
option.set_worker_id(worker_id);
|
|
|
|
|
|
|
|
|
|
if (sparse) {
|
|
|
|
|
for (auto p = 0; p < 10; ++p)
|
|
|
|
|
{
|
|
|
|
|
std::cout << "==> test add " << p + 1 << " /10 rows to *sparse* matrix server" << std::endl;
|
|
|
|
|
auto worker_table = std::shared_ptr<SparseMatrixWorkerTable<int>>(
|
|
|
|
|
new SparseMatrixWorkerTable<int>(num_row, num_col));
|
|
|
|
|
auto server_table = std::shared_ptr<SparseMatrixServerTable<int>>(
|
|
|
|
|
new SparseMatrixServerTable<int>(num_row, num_col, false));
|
|
|
|
|
std::vector<int> row_ids;
|
|
|
|
|
std::vector<int*> data_vec;
|
|
|
|
|
// update (p+1)/10 rows with 1
|
|
|
|
|
for (auto i = 0; i < num_row; ++i) {
|
|
|
|
|
if (i % 10 <= p) {
|
|
|
|
|
row_ids.push_back(i);
|
|
|
|
|
data_vec.push_back(delta + i * num_col);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
worker_table->Add(row_ids, data_vec, num_col, &option);
|
|
|
|
|
worker_table->Get(data, size, -1);
|
|
|
|
|
for (auto i = 0; i < num_row; ++i) {
|
|
|
|
|
auto row_start = data + i * num_col;
|
|
|
|
|
for (auto col = 0; col < num_col; ++col) {
|
|
|
|
|
if (i % 10 <= p) {
|
2016-04-20 16:45:58 +03:00
|
|
|
|
auto expected = i + 2;
|
|
|
|
|
auto actual = *(row_start + col);
|
|
|
|
|
ASSERT_EQ(expected, actual) << "Should be updated after adding";
|
2016-04-19 12:25:20 +03:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ASSERT_EQ(0, *(row_start + col)) << "Should be 0 for non update row values";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-04-19 18:30:18 +03:00
|
|
|
|
timmer.Start();
|
2016-04-19 12:25:20 +03:00
|
|
|
|
worker_table->Get(data, size, worker_id);
|
2016-04-20 13:10:21 +03:00
|
|
|
|
std::cout << " " << 1.0 * timmer.elapse() / 1000 << "s:\t" << "get all rows after adding to rows" << std::endl;
|
2016-04-19 12:25:20 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
for (auto p = 0; p < 10; ++p)
|
|
|
|
|
{
|
|
|
|
|
std::cout << "==> test add " << p + 1 << " /10 rows to matrix server" << std::endl;
|
|
|
|
|
auto worker_table = std::shared_ptr<MatrixWorkerTable<int>>(
|
|
|
|
|
new MatrixWorkerTable<int>(num_row, num_col));
|
|
|
|
|
auto server_table = std::shared_ptr<MatrixServerTable<int>>(
|
|
|
|
|
new MatrixServerTable<int>(num_row, num_col));
|
|
|
|
|
std::vector<int> row_ids;
|
|
|
|
|
std::vector<int*> data_vec;
|
|
|
|
|
// update (p+1)/10 rows with 1
|
|
|
|
|
for (auto i = 0; i < num_row; ++i) {
|
|
|
|
|
if (i % 10 <= p) {
|
|
|
|
|
row_ids.push_back(i);
|
|
|
|
|
data_vec.push_back(delta + i * num_col);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
worker_table->Add(row_ids, data_vec, num_col, &option);
|
|
|
|
|
worker_table->Get(data, size);
|
|
|
|
|
for (auto i = 0; i < num_row; ++i) {
|
|
|
|
|
auto row_start = data + i * num_col;
|
|
|
|
|
for (auto col = 0; col < num_col; ++col) {
|
|
|
|
|
if (i % 10 <= p) {
|
2016-04-20 16:45:58 +03:00
|
|
|
|
auto expected = i + 2;
|
|
|
|
|
auto actual = *(row_start + col);
|
|
|
|
|
ASSERT_EQ(expected, actual) << "Should be updated after adding";
|
2016-04-19 12:25:20 +03:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
ASSERT_EQ(0, *(row_start + col)) << "Should be 0 for non update row values";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-04-19 18:30:18 +03:00
|
|
|
|
timmer.Start();
|
2016-04-19 12:25:20 +03:00
|
|
|
|
worker_table->Get(data, size);
|
2016-04-20 13:10:21 +03:00
|
|
|
|
std::cout << " " << 1.0 * timmer.elapse() / 1000 << "s:\t" << "get all rows after adding to rows" << std::endl;
|
2016-04-19 12:25:20 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-04-19 18:30:18 +03:00
|
|
|
|
Log::ResetLogLevel(LogLevel::Info);
|
|
|
|
|
Dashboard::Display();
|
|
|
|
|
Log::ResetLogLevel(LogLevel::Error);
|
|
|
|
|
|
2016-04-19 12:25:20 +03:00
|
|
|
|
MV_Barrier();
|
|
|
|
|
MV_ShutDown();
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-17 14:56:58 +03:00
|
|
|
|
|
2016-02-02 15:40:07 +03:00
|
|
|
|
int main(int argc, char* argv[]) {
|
2016-02-23 09:15:22 +03:00
|
|
|
|
Log::ResetLogLevel(LogLevel::Debug);
|
2016-04-05 12:07:17 +03:00
|
|
|
|
|
2016-03-30 08:40:20 +03:00
|
|
|
|
if (argc == 1){
|
2016-04-17 14:56:58 +03:00
|
|
|
|
multiverso::MV_Init();
|
|
|
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
|
|
|
auto res = RUN_ALL_TESTS();
|
|
|
|
|
multiverso::MV_ShutDown();
|
|
|
|
|
return res;
|
2016-03-30 08:40:20 +03:00
|
|
|
|
}
|
2016-04-07 15:05:32 +03:00
|
|
|
|
else {
|
2016-02-19 16:11:20 +03:00
|
|
|
|
if (strcmp(argv[1], "kv") == 0) TestKV(argc, argv);
|
|
|
|
|
else if (strcmp(argv[1], "array") == 0) TestArray(argc, argv);
|
|
|
|
|
else if (strcmp(argv[1], "net") == 0) TestNet(argc, argv);
|
2016-02-19 05:46:07 +03:00
|
|
|
|
else if (strcmp(argv[1], "ip") == 0) TestIP();
|
2016-03-09 09:10:53 +03:00
|
|
|
|
else if (strcmp(argv[1], "threads") == 0) TestMultipleThread(argc, argv);
|
|
|
|
|
else if (strcmp(argv[1], "matrix") == 0) TestMatrix(argc, argv);
|
|
|
|
|
else if (strcmp(argv[1], "nonet") == 0) TestNoNet(argc, argv);
|
|
|
|
|
else if (strcmp(argv[1], "checkpoint") == 0) TestCheckPoint(argc, argv, false);
|
|
|
|
|
else if (strcmp(argv[1], "restore") == 0) TestCheckPoint(argc, argv, true);
|
2016-04-17 14:56:58 +03:00
|
|
|
|
else if (strcmp(argv[1], "allreduce") == 0) TestAllreduce(argc, argv);
|
2016-04-19 12:25:20 +03:00
|
|
|
|
else if (strcmp(argv[1], "sparsematrix") == 0) TestSparseMatrixTable(argc, argv);
|
2016-04-19 18:30:18 +03:00
|
|
|
|
else if (strcmp(argv[1], "testsparse0") == 0) TestMatrixPerformance(argc, argv, true);
|
|
|
|
|
else if (strcmp(argv[1], "testsparse1") == 0) TestMatrixPerformance(argc, argv, false);
|
2016-02-02 15:40:07 +03:00
|
|
|
|
else CHECK(false);
|
2016-03-28 05:42:10 +03:00
|
|
|
|
}
|
2016-02-02 15:40:07 +03:00
|
|
|
|
return 0;
|
2016-02-26 09:36:38 +03:00
|
|
|
|
}
|