@@ -71,6 +71,7 @@ enum rpc_cmd {
7171 RPC_CMD_HELLO ,
7272 RPC_CMD_DEVICE_COUNT ,
7373 RPC_CMD_GRAPH_RECOMPUTE ,
74+ RPC_CMD_MEMSET_TENSOR ,
7475 RPC_CMD_COUNT ,
7576};
7677
@@ -152,6 +153,13 @@ struct rpc_msg_buffer_clear_req {
152153 uint8_t value;
153154};
154155
156+ struct rpc_msg_memset_tensor_req {
157+ rpc_tensor tensor;
158+ uint64_t offset;
159+ uint64_t size;
160+ uint8_t value;
161+ };
162+
155163struct rpc_msg_set_tensor_hash_req {
156164 rpc_tensor tensor;
157165 uint64_t offset;
@@ -462,6 +470,19 @@ static enum ggml_status ggml_backend_rpc_buffer_init_tensor(ggml_backend_buffer_
462470 return GGML_STATUS_SUCCESS ;
463471}
464472
473+ static void ggml_backend_rpc_buffer_memset_tensor (
474+ ggml_backend_buffer_t buffer, ggml_tensor * tensor, uint8_t value, size_t offset, size_t size) {
475+ ggml_backend_rpc_buffer_context * ctx = (ggml_backend_rpc_buffer_context *)buffer->context ;
476+ rpc_msg_memset_tensor_req request = {
477+ /* .tensor = */ serialize_tensor (tensor),
478+ /* .offset = */ offset,
479+ /* .size = */ size,
480+ /* .value = */ value,
481+ };
482+ bool status = send_rpc_cmd (ctx->sock , RPC_CMD_MEMSET_TENSOR , &request, sizeof (request), nullptr , 0 );
483+ RPC_STATUS_ASSERT (status);
484+ }
485+
465486static void ggml_backend_rpc_buffer_set_tensor (ggml_backend_buffer_t buffer, ggml_tensor * tensor, const void * data, size_t offset, size_t size) {
466487 ggml_backend_rpc_buffer_context * ctx = (ggml_backend_rpc_buffer_context *)buffer->context ;
467488 rpc_tensor rpc_tensor = serialize_tensor (tensor);
@@ -531,7 +552,7 @@ static ggml_backend_buffer_i ggml_backend_rpc_buffer_interface = {
531552 /* .free_buffer = */ ggml_backend_rpc_buffer_free_buffer,
532553 /* .get_base = */ ggml_backend_rpc_buffer_get_base,
533554 /* .init_tensor = */ ggml_backend_rpc_buffer_init_tensor,
534- /* .memset_tensor = */ NULL ,
555+ /* .memset_tensor = */ ggml_backend_rpc_buffer_memset_tensor ,
535556 /* .set_tensor = */ ggml_backend_rpc_buffer_set_tensor,
536557 /* .get_tensor = */ ggml_backend_rpc_buffer_get_tensor,
537558 /* .set_tensor_2d = */ NULL ,
@@ -831,6 +852,7 @@ class rpc_server {
831852 bool buffer_get_base (const rpc_msg_buffer_get_base_req & request, rpc_msg_buffer_get_base_rsp & response);
832853 bool free_buffer (const rpc_msg_free_buffer_req & request);
833854 bool buffer_clear (const rpc_msg_buffer_clear_req & request);
855+ bool memset_tensor (const rpc_msg_memset_tensor_req & request);
834856 bool set_tensor (const std::vector<uint8_t > & input);
835857 bool set_tensor_hash (const rpc_msg_set_tensor_hash_req & request, rpc_msg_set_tensor_hash_rsp & response);
836858 bool get_tensor (const rpc_msg_get_tensor_req & request, std::vector<uint8_t > & response);
@@ -989,6 +1011,52 @@ bool rpc_server::buffer_clear(const rpc_msg_buffer_clear_req & request) {
9891011 return true ;
9901012}
9911013
1014+ bool rpc_server::memset_tensor (const rpc_msg_memset_tensor_req & request) {
1015+ struct ggml_init_params params {
1016+ /* .mem_size =*/ ggml_tensor_overhead(),
1017+ /* .mem_buffer =*/ NULL ,
1018+ /* .no_alloc =*/ true ,
1019+ };
1020+ ggml_context_ptr ctx_ptr { ggml_init (params) };
1021+ GGML_ASSERT (ctx_ptr != nullptr );
1022+ ggml_context * ctx = ctx_ptr.get ();
1023+ ggml_tensor * tensor = deserialize_tensor (ctx, &request.tensor );
1024+ if (tensor == nullptr || tensor->buffer == nullptr ) {
1025+ GGML_LOG_ERROR (" [%s] error deserializing tensor\n " , __func__);
1026+ return false ;
1027+ }
1028+
1029+ const uint64_t tensor_size = ggml_nbytes (tensor);
1030+ if (request.offset > tensor_size || request.size > tensor_size - request.offset ) {
1031+ GGML_LOG_ERROR (" [%s] tensor region (offset=%" PRIu64 " , size=%" PRIu64 " ) out of tensor bounds [0, %" PRIu64 " )\n " ,
1032+ __func__, request.offset , request.size , tensor_size);
1033+ return false ;
1034+ }
1035+
1036+ const uint64_t buffer_start = (uint64_t ) ggml_backend_buffer_get_base (tensor->buffer );
1037+ const uint64_t buffer_size = ggml_backend_buffer_get_size (tensor->buffer );
1038+ if (request.tensor .data < buffer_start) {
1039+ GGML_LOG_ERROR (" [%s] tensor data before buffer start\n " , __func__);
1040+ return false ;
1041+ }
1042+ const uint64_t data_offset = request.tensor .data - buffer_start;
1043+ if (data_offset > buffer_size ||
1044+ request.offset > buffer_size - data_offset ||
1045+ request.size > buffer_size - data_offset - request.offset ) {
1046+ GGML_LOG_ERROR (" [%s] tensor region out of buffer bounds\n " , __func__);
1047+ return false ;
1048+ }
1049+ if (tensor->buffer ->iface .memset_tensor == nullptr ) {
1050+ GGML_LOG_ERROR (" [%s] memset not implemented by backend buffer\n " , __func__);
1051+ return false ;
1052+ }
1053+
1054+ LOG_DBG (" [%s] buffer: %p, data: %p, offset: %" PRIu64 " , size: %" PRIu64 " , value: %u\n " ,
1055+ __func__, (void *) tensor->buffer , tensor->data , request.offset , request.size , request.value );
1056+ ggml_backend_tensor_memset (tensor, request.value , request.offset , request.size );
1057+ return true ;
1058+ }
1059+
9921060ggml_tensor * rpc_server::deserialize_tensor (struct ggml_context * ctx, const rpc_tensor * tensor) {
9931061 // Validate tensor type before using it
9941062 if (tensor->type >= GGML_TYPE_COUNT ) {
@@ -1585,6 +1653,19 @@ static void rpc_serve_client(const std::vector<ggml_backend_t> & backends, const
15851653 }
15861654 break ;
15871655 }
1656+ case RPC_CMD_MEMSET_TENSOR : {
1657+ rpc_msg_memset_tensor_req request;
1658+ if (!recv_msg (sock, &request, sizeof (request))) {
1659+ return ;
1660+ }
1661+ if (!server.memset_tensor (request)) {
1662+ return ;
1663+ }
1664+ if (!send_msg (sock, nullptr , 0 )) {
1665+ return ;
1666+ }
1667+ break ;
1668+ }
15881669 case RPC_CMD_SET_TENSOR : {
15891670 std::vector<uint8_t > input;
15901671 if (!recv_msg (sock, input)) {
0 commit comments