Currently, for distributed training, gradients are splitted before send_op and the parameters are concatenated after the send_op. Both of these two steps require additional memory copy and memory usage. We should share the memory between the original gradients and splitted gradients, and between splitted parameter and original parameter.
One possible way to do this is to add another operator similar to split_op, but using Tensor::slice() to share the memory with the input.