NVIDIA / NVIDIA/cudf

[FEA] cuio: allow datasource and data_sink to decide how device/host read/write/copies are handled.

Open
#6,187 10 comments 0 reactions 0 assignees View on GitHub
cuIO feature request libcudf
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.