[FEA] cuio: allow datasource and data_sink to decide how device/host read/write/copies are handled.
- Dominant language
- C++
- Stars
- 9.8k
- Forks
- 1.1k
- Avg merge
- 3d 6m
- Merged PRs (30d)
- 278
Description
Reader and writer implementations have multiple paths for reading and writing, depending whether data is read-from/written-to the host or the device. This logic could be delegated to `datasource` and `data_sink`, potentially sharing the functionality between all `datasource`s and `data_sink`s.
This would eliminate the need for `supports_device_write` and `supports_device_read`, which could also reduce the surface area of testing.
note: `supports_device_read` is currently unused.
Examples:
https://github.com/rapidsai/cudf/blob/f4735c7f658da4a157dc09391da899b072878305/cpp/src/io/csv/writer_impl.cu#L412-L442
https://github.com/rapidsai/cudf/blob/f4735c7f658da4a157dc09391da899b072878305/cpp/src/io/parquet/writer_impl.cu#L882-L913
Looks like ORC doesn't have this logic at all, which might be a bug?
https://github.com/rapidsai/cudf/blob/f4735c7f658da4a157dc09391da899b072878305/cpp/src/io/orc/writer_impl.cu#L1246
Hypothetical Source/Sink APIs
-
`data_kind` is used to describe the caller-owned buffer.
```C++
// note: data_kind is not used to determine the sink/source buffer's kind.
// the sink/source buffer kind is an implementation detail of the given sink/source.
enum class data_kind {
host, // used when the caller is writing data from host, or reading data to host
device // used when the caller is writing data from device, or reading data to device
};
```
An API such as this delegates the read/write logic to the source/sink, but gives enough information for the source/sink to determine how data should be copied, and whether or not a sync is necessary to perform the copies. For instance, if the specific source implementation is reading data on device, and the `read(...)` call is made with `data_kind::device`, then the source has enough information to execute a device-to-device copy, without or without syncing the stream (perhaps an API an optional method should be added to ensure sync has taken place).
```C++
class base_source_context {
base_source_context(cudaStream_t stream) : stream(stream) {}
virtual size_t read(uint8_t const* data, size_t size, data_kind kind) = 0;
private:
cudaStream_t stream;
};
class base_source {
public:
virtual unique_ptr begin_read(cudaStream_t stream) = 0;
};
```
```C++
class base_sink_context {
public:
base_sink_context(cudaStream_t stream) : stream(stream) {}
virtual void write(uint8_t const* data, size_t size, data_kind kind) = 0;
private:
cudaStream_t stream;
};
class base_sink {
public:
virtual unique_ptr begin_write(cudaStream_t stream) = 0;
};
```
Contributor guide
Assessment
This issue has not been assessed yet.