UniformGpuScheme violates Rule of Five
The `gpu::communication::UniformGpuScheme` class violates the C++ [rule of five](https://en.cppreference.com/w/cpp/language/rule_of_three); its copy and move semantics are invalid.
`UniformGpuScheme` objects manage system ressources, namely a set of GPU streams. These are created in its constructor and destroyed in its destructor. However, it does not define custom copy and move constructors, so whenever a UniformGpuScheme object is copied or moved, and the destructor is called on the original, all streams are destroyed. Subsequently, when the comm scheme executes kernels, hard-to-track CUDA and HIP runtime errors ensue.
## Suggested Fix
Either fix copy and move semantics (preferred!) or make objects of the class non-copyable and non-movable.
## Ideas
CUDA streams are system ressources that are used in many corners of our code base.
The best way to handle their lifetimes would be to wrap streams into RAII objects.
Implement a [RAII](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rr-raii) class for managing a single stream, and then use this class inside UniformGpuScheme to get correct copy and move semantics.
issue