23 , gpu_layers_(gpu_layers) {
48 Logger::log(
"MPI initialized - Rank: " + std::to_string(
rank_) +
110 std::to_string(
static_cast<int>(
local_info.role)) +
"|" +
111 std::to_string(
local_info.has_gpu ? 1 : 0) +
"|" +
112 std::to_string(
local_info.gpu_memory_mb) +
"|" +
137 if (std::getline(
ss, hostname,
'|') &&
171 if (std::getline(
ss, hostname,
'|') &&
189 Logger::log(
"Node " + std::to_string(
node.rank) +
": " +
node.hostname +
190 " (GPU: " + (
node.has_gpu ?
"yes" :
"no") +
200 Logger::log(
"Only master node (rank 0) can submit requests",
Logger::ERROR);
209 if (target_node == -1) {
214 error_result.error_message =
"No available worker nodes";
222 Logger::log(
"Failed to send request to worker node " + std::to_string(target_node),
Logger::ERROR);
226 error_result.error_message =
"Failed to send request to worker";
251 if (
node.rank == 0)
continue;
269 int size =
static_cast<int>(
serialized.size());
290 Logger::log(
"Starting worker node (rank " + std::to_string(
rank_) +
")",
Logger::INFO);
309 std::this_thread::sleep_for(std::chrono::milliseconds(10));
332 std::this_thread::sleep_for(std::chrono::milliseconds(10));
337 auto now = std::chrono::steady_clock::now();
362 std::vector<char>
buffer(size);
407 std::vector<char>
buffer(size);
437 int size =
static_cast<int>(
serialized.size());
452 std::ostringstream
oss;
459 <<
request.system_prompt <<
"|"
462 std::string
str =
oss.str();
463 return std::vector<char>(
str.begin(),
str.end());
467 std::string
str(data.begin(), data.end());
468 std::istringstream
iss(
str);
473 if (std::getline(
iss,
request.request_id,
'|') &&
475 std::getline(
iss,
temp,
'|')) {
478 if (std::getline(
iss,
temp,
'|')) {
481 if (std::getline(
iss,
temp,
'|')) {
484 if (std::getline(
iss,
temp,
'|')) {
487 if (std::getline(
iss,
request.system_prompt,
'|') &&
496 std::ostringstream
oss;
498 <<
result.generated_text <<
"|"
499 <<
result.tokens_generated <<
"|"
500 <<
result.inference_time_ms <<
"|"
501 <<
result.processing_node <<
"|"
502 << (
result.success ? 1 : 0) <<
"|"
505 std::string
str =
oss.str();
506 return std::vector<char>(
str.begin(),
str.end());
510 std::string
str(data.begin(), data.end());
511 std::istringstream
iss(
str);
516 if (std::getline(
iss,
result.request_id,
'|') &&
517 std::getline(
iss,
result.generated_text,
'|') &&
518 std::getline(
iss,
temp,
'|')) {
521 if (std::getline(
iss,
temp,
'|')) {
524 if (std::getline(
iss,
temp,
'|')) {
527 if (std::getline(
iss,
temp,
'|')) {
530 if (std::getline(
iss,
result.error_message)) {
542 auto start_time = std::chrono::high_resolution_clock::now();
549 result.generated_text =
"Generated response for: " +
request.prompt;
558 }
catch (
const std::exception&
e) {
560 result.error_message =
e.what();
563 auto end_time = std::chrono::high_resolution_clock::now();
596 if (
stats.completed_requests > 0) {
597 stats.average_response_time_ms = 0.0f;
601 stats.requests_per_node[
node.rank] =
node.active_requests.load();
static constexpr int TAG_SHUTDOWN
std::atomic< int > total_requests_
std::atomic< int > completed_requests_
~DistributedCoordinator()
InferenceResult process_inference_locally(const InferenceRequest &request)
Process inference request locally.
bool send_result_to_master(const InferenceResult &result)
Send result back to master.
void discover_cluster()
Discover cluster topology and node capabilities.
static constexpr int TAG_NODE_INFO
void shutdown()
Shutdown MPI and cleanup resources.
static constexpr int TAG_REQUEST
bool receive_and_process_request()
Receive and process request (worker node)
bool initialize()
Initialize MPI and discover network topology.
std::vector< char > serialize_request(const InferenceRequest &request)
Serialize request for MPI transmission.
static constexpr int TAG_RESULT
bool submit_request(const InferenceRequest &request, std::function< void(const InferenceResult &)> callback)
Submit an inference request (master node only)
bool receive_result_from_worker()
Receive result from worker (master node)
void run_worker()
Process requests as a worker node This function blocks and processes incoming requests.
std::vector< NodeInfo > cluster_nodes_
void handle_heartbeat(int source_rank)
Handle heartbeat from other nodes.
bool send_request_to_worker(int worker_rank, const InferenceRequest &request)
Send request to worker node.
void send_heartbeat()
Send heartbeat to all nodes.
std::atomic< int > failed_requests_
DistributedCoordinator(NodeRole role, const std::string &model_path, const std::string &tokenizer_path, int gpu_layers=-1)
Initialize the distributed coordinator.
std::map< std::string, std::function< void(const InferenceResult &)> > pending_callbacks_
LoadStats get_load_stats() const
std::vector< NodeInfo > get_cluster_info() const
Get information about all nodes in the cluster.
static constexpr int TAG_HEARTBEAT
std::vector< char > serialize_result(const InferenceResult &result)
Serialize result for MPI transmission.
InferenceRequest deserialize_request(const std::vector< char > &data)
Deserialize request from MPI transmission.
void run_master()
Run as master node, coordinating requests This function blocks and coordinates the distributed system...
int select_optimal_node(const InferenceRequest &request)
Select optimal node for processing request.
InferenceResult deserialize_result(const std::vector< char > &data)
Deserialize result from MPI transmission.
bool is_mpi_available() const
Check if MPI is available and initialized.
std::map< std::string, std::string > role_
Logging utilities for the TinyLlama implementation.
Get load balancing statistics.