Skip to content

Commit

Permalink
Add gRPC-rere support for the C++ SDK (#2537)
Browse files Browse the repository at this point in the history
  • Loading branch information
charlesbvll authored Oct 30, 2023
1 parent 78163cb commit ffcca20
Show file tree
Hide file tree
Showing 12 changed files with 601 additions and 87 deletions.
6 changes: 5 additions & 1 deletion doc/source/ref-changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@

## Unreleased

### What's new?

- **Support custom** `ClientManager` **in** `start_driver()` ([#2292](https://github.com/adap/flower/pull/2292))

- **Update REST API to support create and delete nodes** ([#2283](https://github.com/adap/flower/pull/2283))

### What's new?
- **Update the C++ SDK** ([#2537](https://github/com/adap/flower/pull/2537), [#2528](https://github/com/adap/flower/pull/2528), [#2523](https://github.com/adap/flower/pull/2523), [#2522](https://github.com/adap/flower/pull/2522))

Add gRPC request-response capability to the C++ SDK.

- **Fix the incorrect return types of Strategy** ([#2432](https://github.com/adap/flower/pull/2432/files))

Expand Down
113 changes: 97 additions & 16 deletions examples/quickstart-cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,34 +30,115 @@ endif()

######################
### FLWR_GRPC_PROTO
get_filename_component(FLWR_PROTO_BASE_PATH "../../src/proto/" ABSOLUTE)
get_filename_component(FLWR_TRANS_PROTO "../../src/proto/flwr/proto/transport.proto" ABSOLUTE)
get_filename_component(FLWR_NODE_PROTO "../../src/proto/flwr/proto/node.proto" ABSOLUTE)
get_filename_component(FLWR_TASK_PROTO "../../src/proto/flwr/proto/task.proto" ABSOLUTE)
get_filename_component(FLWR_FLEET_PROTO "../../src/proto/flwr/proto/fleet.proto" ABSOLUTE)

set(FLWR_TRANS_PROTO_SRCS "${CMAKE_CURRENT_BINARY_DIR}/flwr/proto/transport.pb.cc")
set(FLWR_TRANS_PROTO_HDRS "${CMAKE_CURRENT_BINARY_DIR}/flwr/proto/transport.pb.h")
set(FLWR_TRANS_GRPC_SRCS "${CMAKE_CURRENT_BINARY_DIR}/flwr/proto/transport.grpc.pb.cc")
set(FLWR_TRANS_GRPC_HDRS "${CMAKE_CURRENT_BINARY_DIR}/flwr/proto/transport.grpc.pb.h")

set(FLWR_NODE_PROTO_SRCS "${CMAKE_CURRENT_BINARY_DIR}/flwr/proto/node.pb.cc")
set(FLWR_NODE_PROTO_HDRS "${CMAKE_CURRENT_BINARY_DIR}/flwr/proto/node.pb.h")
set(FLWR_NODE_GRPC_SRCS "${CMAKE_CURRENT_BINARY_DIR}/flwr/proto/node.grpc.pb.cc")
set(FLWR_NODE_GRPC_HDRS "${CMAKE_CURRENT_BINARY_DIR}/flwr/proto/node.grpc.pb.h")

set(FLWR_TASK_PROTO_SRCS "${CMAKE_CURRENT_BINARY_DIR}/flwr/proto/task.pb.cc")
set(FLWR_TASK_PROTO_HDRS "${CMAKE_CURRENT_BINARY_DIR}/flwr/proto/task.pb.h")
set(FLWR_TASK_GRPC_SRCS "${CMAKE_CURRENT_BINARY_DIR}/flwr/proto/task.grpc.pb.cc")
set(FLWR_TASK_GRPC_HDRS "${CMAKE_CURRENT_BINARY_DIR}/flwr/proto/task.grpc.pb.h")

set(FLWR_FLEET_PROTO_SRCS "${CMAKE_CURRENT_BINARY_DIR}/flwr/proto/fleet.pb.cc")
set(FLWR_FLEET_PROTO_HDRS "${CMAKE_CURRENT_BINARY_DIR}/flwr/proto/fleet.pb.h")
set(FLWR_FLEET_GRPC_SRCS "${CMAKE_CURRENT_BINARY_DIR}/flwr/proto/fleet.grpc.pb.cc")
set(FLWR_FLEET_GRPC_HDRS "${CMAKE_CURRENT_BINARY_DIR}/flwr/proto/fleet.grpc.pb.h")

get_filename_component(FLWR_PROTO "../../src/proto/flwr/proto/transport.proto" ABSOLUTE)
get_filename_component(FLWR_PROTO_PATH "${FLWR_PROTO}" PATH)
# External building command to generate gRPC source files.
add_custom_command(
OUTPUT "${FLWR_TRANS_PROTO_SRCS}"
"${FLWR_TRANS_PROTO_HDRS}"
"${FLWR_TRANS_GRPC_SRCS}"
"${FLWR_TRANS_GRPC_HDRS}"
COMMAND ${_PROTOBUF_PROTOC}
ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}"
--cpp_out "${CMAKE_CURRENT_BINARY_DIR}"
-I "${FLWR_PROTO_BASE_PATH}"
--plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}"
"${FLWR_TRANS_PROTO}"
DEPENDS "${FLWR_TRANS_PROTO}"
)

add_custom_command(
OUTPUT
"${FLWR_NODE_PROTO_SRCS}"
"${FLWR_NODE_PROTO_HDRS}"
"${FLWR_NODE_GRPC_SRCS}"
"${FLWR_NODE_GRPC_HDRS}"
COMMAND ${_PROTOBUF_PROTOC}
ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}"
--cpp_out "${CMAKE_CURRENT_BINARY_DIR}"
-I "${FLWR_PROTO_BASE_PATH}"
--plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}"
"${FLWR_NODE_PROTO}"
DEPENDS
"${FLWR_NODE_PROTO}"
)

set(FLWR_PROTO_SRCS "${CMAKE_CURRENT_BINARY_DIR}/transport.pb.cc")
set(FLWR_PROTO_HDRS "${CMAKE_CURRENT_BINARY_DIR}/transport.pb.h")
set(FLWR_GRPC_SRCS "${CMAKE_CURRENT_BINARY_DIR}/transport.grpc.pb.cc")
set(FLAR_GRPC_HDRS "${CMAKE_CURRENT_BINARY_DIR}/transport.grpc.pb.h")
add_custom_command(
OUTPUT
"${FLWR_TASK_PROTO_SRCS}"
"${FLWR_TASK_PROTO_HDRS}"
"${FLWR_TASK_GRPC_SRCS}"
"${FLWR_TASK_GRPC_HDRS}"
COMMAND ${_PROTOBUF_PROTOC}
ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}"
--cpp_out "${CMAKE_CURRENT_BINARY_DIR}"
-I "${FLWR_PROTO_BASE_PATH}"
--plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}"
"${FLWR_TASK_PROTO}"
DEPENDS
"${FLWR_TASK_PROTO}"
)

# External building command to generate gRPC source files.
add_custom_command(
OUTPUT "${FLWR_PROTO_SRCS}" "${FLWR_PROTO_HDRS}" "${FLWR_GRPC_SRCS}" "${FLWR_GRPC_HDRS}"
OUTPUT
"${FLWR_FLEET_PROTO_SRCS}"
"${FLWR_FLEET_PROTO_HDRS}"
"${FLWR_FLEET_GRPC_SRCS}"
"${FLWR_FLEET_GRPC_HDRS}"
COMMAND ${_PROTOBUF_PROTOC}
ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}"
--cpp_out "${CMAKE_CURRENT_BINARY_DIR}"
-I "${FLWR_PROTO_PATH}"
-I "${FLWR_PROTO_BASE_PATH}"
--plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}"
"${FLWR_PROTO}"
DEPENDS "${FLWR_PROTO}"
"${FLWR_FLEET_PROTO}"
DEPENDS
"${FLWR_FLEET_PROTO}"
)

add_library(flwr_grpc_proto
${FLWR_GRPC_SRCS}
${FLWR_GRPC_HDRS}
${FLWR_PROTO_SRCS}
${FLWR_PROTO_HDRS}
add_library(flwr_grpc_proto STATIC
${FLWR_TRANS_GRPC_SRCS}
${FLWR_TRANS_GRPC_HDRS}
${FLWR_TRANS_PROTO_SRCS}
${FLWR_TRANS_PROTO_HDRS}
${FLWR_NODE_GRPC_SRCS}
${FLWR_NODE_GRPC_HDRS}
${FLWR_NODE_PROTO_SRCS}
${FLWR_NODE_PROTO_HDRS}
${FLWR_TASK_GRPC_SRCS}
${FLWR_TASK_GRPC_HDRS}
${FLWR_TASK_PROTO_SRCS}
${FLWR_TASK_PROTO_HDRS}
${FLWR_FLEET_GRPC_SRCS}
${FLWR_FLEET_GRPC_HDRS}
${FLWR_FLEET_PROTO_SRCS}
${FLWR_FLEET_PROTO_HDRS}
)


target_include_directories(flwr_grpc_proto PUBLIC ${CMAKE_CURRENT_BINARY_DIR})

target_link_libraries(flwr_grpc_proto
Expand Down
10 changes: 10 additions & 0 deletions examples/quickstart-cpp/driver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import flwr as fl
from fedavg_cpp import FedAvgCpp

# Start Flower server for three rounds of federated learning
if __name__ == "__main__":
fl.driver.start_driver(
server_address="0.0.0.0:9091",
config=fl.server.ServerConfig(num_rounds=3),
strategy=FedAvgCpp(),
)
90 changes: 52 additions & 38 deletions examples/quickstart-cpp/src/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,58 @@
#include "start.h"

int main(int argc, char **argv) {
if (argc != 3) {
std::cout << "Client takes three arguments as follows: " << std::endl;
std::cout << "./client CLIENT_ID SERVER_URL" << std::endl;
std::cout << "Example: ./flwr_client 0 '127.0.0.1:8080'" << std::endl;
return 0;
}

// Parsing arguments
const std::string CLIENT_ID = argv[1];
const std::string SERVER_URL = argv[2];

// Populate local datasets
std::vector<double> ms{3.5, 9.3}; // b + m_0*x0 + m_1*x1
double b = 1.7;
std::cout <<"Training set:" << std::endl;
SyntheticDataset local_training_data = SyntheticDataset(ms, b, 1000);
std::cout << std::endl;

std::cout <<"Validation set:" << std::endl;
SyntheticDataset local_validation_data = SyntheticDataset(ms, b, 100);
std::cout << std::endl;

std::cout <<"Test set:" << std::endl;
SyntheticDataset local_test_data = SyntheticDataset(ms, b, 500);
std::cout << std::endl;

// Define a model
LineFitModel model = LineFitModel(500, 0.01, ms.size());

// Initialize TorchClient
SimpleFlwrClient client(CLIENT_ID, model, local_training_data, local_validation_data, local_test_data);

// Define a server address
std::string server_add = SERVER_URL;

// Start client
if (argc != 3 && argc != 4) {
std::cout << "Client takes three mandatory arguments and one optional as "
"follows: "
<< std::endl;
std::cout << "./client CLIENT_ID SERVER_URL [GRPC_MODE]" << std::endl;
std::cout
<< "GRPC_MODE is optional and can be either 'bidi' (default) or 'rere'."
<< std::endl;
std::cout << "Example: ./flwr_client 0 '127.0.0.1:8080' bidi" << std::endl;
std::cout << "This is the same as: ./flwr_client 0 '127.0.0.1:8080'"
<< std::endl;
return 0;
}

// Parsing arguments
const std::string CLIENT_ID = argv[1];
const std::string SERVER_URL = argv[2];

// Populate local datasets
std::vector<double> ms{3.5, 9.3}; // b + m_0*x0 + m_1*x1
double b = 1.7;
std::cout << "Training set:" << std::endl;
SyntheticDataset local_training_data = SyntheticDataset(ms, b, 1000);
std::cout << std::endl;

std::cout << "Validation set:" << std::endl;
SyntheticDataset local_validation_data = SyntheticDataset(ms, b, 100);
std::cout << std::endl;

std::cout << "Test set:" << std::endl;
SyntheticDataset local_test_data = SyntheticDataset(ms, b, 500);
std::cout << std::endl;

// Define a model
LineFitModel model = LineFitModel(500, 0.01, ms.size());

// Initialize TorchClient
SimpleFlwrClient client(CLIENT_ID, model, local_training_data,
local_validation_data, local_test_data);

// Define a server address
std::string server_add = SERVER_URL;

if (argc == 4 && std::string(argv[3]) == "rere") {
std::cout << "Starting rere client" << std::endl;
// Start rere client
start::start_rere_client(server_add, &client);
} else {
std::cout << "Starting bidi client" << std::endl;
// Start bidi client
start::start_client(server_add, &client);
}

return 0;
return 0;
}

Loading

0 comments on commit ffcca20

Please sign in to comment.