Skip to content

Commit 09b822f

Browse files
pschuhtensorflower-gardener
authored andcommitted
Move CommonPjRtRawBuffer::CopyRawHostToDeviceAndReturnEvent and
CopyRawDeviceToHostAndReturnEvent to PjRtRawBuffer and introduce PjRtRawBufferInterface which hides the common c-api implementations. PiperOrigin-RevId: 931432961
1 parent d14f17d commit 09b822f

8 files changed

Lines changed: 213 additions & 32 deletions

third_party/xla/xla/pjrt/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,6 +1536,7 @@ cc_library(
15361536
"//xla:literal",
15371537
"//xla:shape_util",
15381538
"//xla/pjrt/c:pjrt_c_api_raw_buffer_extension_hdrs",
1539+
"//xla/pjrt/c:pjrt_c_api_status_utils",
15391540
"//xla/tsl/concurrency:async_value",
15401541
"//xla/tsl/concurrency:ref_count",
15411542
"//xla/tsl/platform:status_macros",

third_party/xla/xla/pjrt/c/BUILD

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,10 @@ cc_library(
314314
name = "pjrt_c_api_raw_buffer_extension_hdrs",
315315
hdrs = ["pjrt_c_api_raw_buffer_extension.h"],
316316
visibility = ["//visibility:public"],
317-
deps = [":pjrt_c_api_hdrs"],
317+
deps = [
318+
":pjrt_c_api_device_event_hdrs",
319+
":pjrt_c_api_hdrs",
320+
],
318321
)
319322

320323
cc_library(

third_party/xla/xla/pjrt/c/pjrt_c_api_raw_buffer_extension.h

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ limitations under the License.
2020
#include <stdint.h>
2121

2222
#include "xla/pjrt/c/pjrt_c_api.h"
23+
#include "xla/pjrt/c/pjrt_c_api_device_event.h"
2324

2425
#ifdef __cplusplus
2526
extern "C" {
@@ -34,18 +35,43 @@ typedef struct PJRT_RawBuffer_FunctionTable {
3435
void (*inc_ref)(PJRT_RawBuffer* raw_buffer);
3536
void (*dec_ref)(PJRT_RawBuffer* raw_buffer);
3637
// Gets the number of bytes of the buffer storage on the device
37-
size_t (*get_on_device_size_in_bytes)(PJRT_RawBuffer* raw_buffer);
38+
size_t (*get_on_device_size_in_bytes)(const PJRT_RawBuffer* raw_buffer);
3839
// Gets the memory space that this buffer is attached to.
39-
PJRT_Memory* (*get_memory_space)(PJRT_RawBuffer* raw_buffer);
40+
PJRT_Memory* (*get_memory_space)(const PJRT_RawBuffer* raw_buffer);
4041
// If visible to the host, returns the base pointer for direct access.
41-
void* (*get_host_pointer)(PJRT_RawBuffer* raw_buffer);
42+
void* (*get_host_pointer)(const PJRT_RawBuffer* raw_buffer);
43+
// Transfers the buffer to a sub-range of the on-device representation.
44+
// offset+transfer_size must be less than get_on_device_size_in_bytes. The
45+
// returned event transitions to ready on error, or after the transfer has
46+
// completed.
47+
//
48+
// Note that the underlying driver may have requirements
49+
// on the alignment of `src` and `offset` as well. Look at implementations of
50+
// this method for specific alignment requirements.
51+
PJRT_Error* (*copy_raw_host_to_device_and_return_event)(
52+
PJRT_RawBuffer* raw_buffer, const void* src, int64_t offset,
53+
int64_t transfer_size, PJRT_DeviceEvent* event);
54+
// Transfers a sub-range of the on-device representation of the buffer.
55+
// offset+transfer_size must be less than get_on_device_size_in_bytes. The
56+
// returned event transitions to ready on error, or after the transfer has
57+
// completed.
58+
//
59+
// Note that the underlying driver may have requirements
60+
// on the alignment of `dst` and `offset` as well. Look at implementations of
61+
// this method for specific alignment requirements.
62+
PJRT_Error* (*copy_raw_device_to_host_and_return_event)(
63+
PJRT_RawBuffer* raw_buffer, void* dst, int64_t offset,
64+
int64_t transfer_size, PJRT_DeviceEvent* event);
65+
// Return opaque device memory pointer to the underlying memory.
66+
void* (*opaque_device_memory_data_pointer)(const PJRT_RawBuffer* raw_buffer);
4267
} PJRT_RawBuffer_FunctionTable;
4368

4469
struct PJRT_RawBuffer {
4570
const PJRT_RawBuffer_FunctionTable* vtable;
4671
};
4772

48-
PJRT_DEFINE_STRUCT_TRAITS(PJRT_RawBuffer_FunctionTable, get_host_pointer);
73+
PJRT_DEFINE_STRUCT_TRAITS(PJRT_RawBuffer_FunctionTable,
74+
opaque_device_memory_data_pointer);
4975
PJRT_DEFINE_STRUCT_TRAITS(PJRT_RawBuffer, vtable);
5076

5177
struct PJRT_RawBuffer_CreateRawAliasOfBuffer_Args {

third_party/xla/xla/pjrt/c/pjrt_c_api_raw_buffer_external.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,26 @@ Future<> PjRtCApiRawBuffer::CopyRawDeviceToHost(void* dst, int64_t offset,
177177
c_api_, c_extension_, c_buffer_, dst, offset, transfer_size);
178178
}
179179

180+
absl::StatusOr<PjRtDeviceEventRef>
181+
PjRtCApiRawBuffer::CopyRawHostToDeviceAndReturnEvent(const void* src,
182+
int64_t offset,
183+
int64_t transfer_size) {
184+
return static_cast<PjRtRawBufferInterface*>(c_buffer_)
185+
->CopyRawHostToDeviceAndReturnEvent(src, offset, transfer_size);
186+
}
187+
188+
absl::StatusOr<PjRtDeviceEventRef>
189+
PjRtCApiRawBuffer::CopyRawDeviceToHostAndReturnEvent(void* dst, int64_t offset,
190+
int64_t transfer_size) {
191+
return static_cast<PjRtRawBufferInterface*>(c_buffer_)
192+
->CopyRawDeviceToHostAndReturnEvent(dst, offset, transfer_size);
193+
}
194+
195+
void* PjRtCApiRawBuffer::OpaqueDeviceMemoryDataPointer() const {
196+
return static_cast<PjRtRawBufferInterface*>(c_buffer_)
197+
->OpaqueDeviceMemoryDataPointer();
198+
}
199+
180200
static std::optional<absl::StatusOr<tsl::RCReference<PjRtRawBuffer>>>
181201
PjRtCApiBuffer_CreateRawAliasOfBuffer_Factory(PjRtBuffer* buffer) {
182202
if (auto* c_api_buffer = dynamic_cast<xla::PjRtCApiBuffer*>(buffer)) {

third_party/xla/xla/pjrt/c/pjrt_c_api_raw_buffer_external.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ class PjRtCApiRawBuffer : public PjRtRawBuffer {
7575
int64_t transfer_size) override;
7676
Future<> CopyRawDeviceToHost(void* dst, int64_t offset,
7777
int64_t transfer_size) override;
78+
absl::StatusOr<PjRtDeviceEventRef> CopyRawHostToDeviceAndReturnEvent(
79+
const void* src, int64_t offset, int64_t transfer_size) override;
80+
absl::StatusOr<PjRtDeviceEventRef> CopyRawDeviceToHostAndReturnEvent(
81+
void* dst, int64_t offset, int64_t transfer_size) override;
82+
void* OpaqueDeviceMemoryDataPointer() const override;
7883

7984
private:
8085
PJRT_RawBuffer* c_buffer_;

third_party/xla/xla/pjrt/c/pjrt_c_api_raw_buffer_internal.cc

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,10 @@ PJRT_Error* PJRT_RawBuffer_CopyRawHostToDevice(
8686
PJRT_RETURN_IF_ERROR(ActualStructSizeIsGreaterOrEqual(
8787
"PJRT_RawBuffer_CopyRawHostToDevice_Args",
8888
PJRT_RawBuffer_CopyRawHostToDevice_Args_STRUCT_SIZE, args->struct_size));
89-
auto* cpp_buffer = static_cast<xla::PjRtRawBuffer*>(args->buffer);
90-
auto result = cpp_buffer->CopyRawHostToDevice(args->src, args->offset,
91-
args->transfer_size);
92-
args->event = new PJRT_Event{std::move(result)};
89+
auto* interface = static_cast<xla::PjRtRawBufferInterface*>(args->buffer);
90+
auto future = interface->CopyRawHostToDevice(args->src, args->offset,
91+
args->transfer_size);
92+
args->event = new PJRT_Event{std::move(future)};
9393
return nullptr;
9494
}
9595

@@ -98,10 +98,10 @@ PJRT_Error* PJRT_RawBuffer_CopyRawDeviceToHost(
9898
PJRT_RETURN_IF_ERROR(ActualStructSizeIsGreaterOrEqual(
9999
"PJRT_RawBuffer_CopyRawDeviceToHost_Args",
100100
PJRT_RawBuffer_CopyRawDeviceToHost_Args_STRUCT_SIZE, args->struct_size));
101-
auto* cpp_buffer = static_cast<xla::PjRtRawBuffer*>(args->buffer);
102-
auto result = cpp_buffer->CopyRawDeviceToHost(args->dst, args->offset,
103-
args->transfer_size);
104-
args->event = new PJRT_Event{std::move(result)};
101+
auto* interface = static_cast<xla::PjRtRawBufferInterface*>(args->buffer);
102+
auto future = interface->CopyRawDeviceToHost(args->dst, args->offset,
103+
args->transfer_size);
104+
args->event = new PJRT_Event{std::move(future)};
105105
return nullptr;
106106
}
107107

third_party/xla/xla/pjrt/raw_buffer.cc

Lines changed: 110 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ limitations under the License.
1515

1616
#include "xla/pjrt/raw_buffer.h"
1717

18+
#include <cstddef>
1819
#include <utility>
1920
#include <vector>
2021

@@ -27,6 +28,7 @@ limitations under the License.
2728
#include "xla/future.h"
2829
#include "xla/pjrt/async_work_runner.h"
2930
#include "xla/pjrt/c/pjrt_c_api_raw_buffer_extension.h"
31+
#include "xla/pjrt/c/pjrt_c_api_status_utils.h"
3032
#include "xla/pjrt/device_event.h"
3133
#include "xla/pjrt/device_event_utils.h"
3234
#include "xla/pjrt/pjrt_client.h"
@@ -73,6 +75,19 @@ class WrappedPjRtStagingBuffer : public PjRtStagingBuffer {
7375
private:
7476
tsl::AsyncValueRef<PjRtStagingBuffer> real_buffer_;
7577
};
78+
79+
Future<> ConvertEventToFuture(PjRtDeviceEventRef event) {
80+
auto [promise, future] = tsl::MakePromise<void>();
81+
event.AndThen([promise = std::move(promise), event]() mutable {
82+
auto error = event.GetErrorIfPresent();
83+
if (error.has_value() && !error->ok()) {
84+
promise.Set(*error);
85+
} else {
86+
promise.Set();
87+
}
88+
});
89+
return std::move(future);
90+
}
7691
} // namespace
7792

7893
std::vector<RegisterRawBufferFactory::FactoryFuncT>& GetFactoryFuncs() {
@@ -224,21 +239,110 @@ const PJRT_RawBuffer_FunctionTable PjRtRawBuffer::kRawBufferVtable = {
224239
static_cast<PjRtRawBuffer*>(raw_buffer)->DropRef();
225240
},
226241
/*get_on_device_size_in_bytes=*/
227-
+[](PJRT_RawBuffer* raw_buffer) -> size_t {
228-
return static_cast<PjRtRawBuffer*>(raw_buffer)->GetOnDeviceSizeInBytes();
242+
+[](const PJRT_RawBuffer* raw_buffer) -> size_t {
243+
return static_cast<const PjRtRawBuffer*>(raw_buffer)
244+
->GetOnDeviceSizeInBytes();
229245
},
230246
/*get_memory_space=*/
231-
+[](PJRT_RawBuffer* raw_buffer) -> PJRT_Memory* {
232-
return static_cast<PjRtRawBuffer*>(raw_buffer)
247+
+[](const PJRT_RawBuffer* raw_buffer) -> PJRT_Memory* {
248+
return static_cast<const PjRtRawBuffer*>(raw_buffer)
233249
->memory_space()
234250
->ToCApiPtr();
235251
},
236252
/*get_host_pointer=*/
237-
+[](PJRT_RawBuffer* raw_buffer) -> void* {
238-
return static_cast<PjRtRawBuffer*>(raw_buffer)->GetHostPointer();
253+
+[](const PJRT_RawBuffer* raw_buffer) -> void* {
254+
return static_cast<const PjRtRawBuffer*>(raw_buffer)->GetHostPointer();
255+
},
256+
/*copy_raw_host_to_device_and_return_event=*/
257+
+[](PJRT_RawBuffer* raw_buffer, const void* src, int64_t offset,
258+
int64_t transfer_size, PJRT_DeviceEvent* event) -> PJRT_Error* {
259+
auto result =
260+
static_cast<PjRtRawBuffer*>(raw_buffer)
261+
->CopyRawHostToDeviceAndReturnEvent(src, offset, transfer_size);
262+
if (!result.ok()) {
263+
return pjrt::StatusToPjRtError(result.status());
264+
}
265+
*event = std::move(*result).release().ToC();
266+
return nullptr;
267+
},
268+
/*copy_raw_device_to_host_and_return_event=*/
269+
+[](PJRT_RawBuffer* raw_buffer, void* dst, int64_t offset,
270+
int64_t transfer_size, PJRT_DeviceEvent* event) -> PJRT_Error* {
271+
auto result =
272+
static_cast<PjRtRawBuffer*>(raw_buffer)
273+
->CopyRawDeviceToHostAndReturnEvent(dst, offset, transfer_size);
274+
if (!result.ok()) {
275+
return pjrt::StatusToPjRtError(result.status());
276+
}
277+
*event = std::move(*result).release().ToC();
278+
return nullptr;
279+
},
280+
/*opaque_device_memory_data_pointer=*/
281+
+[](const PJRT_RawBuffer* raw_buffer) -> void* {
282+
return static_cast<const PjRtRawBuffer*>(raw_buffer)
283+
->OpaqueDeviceMemoryDataPointer();
239284
},
240285
};
241286

242287
PjRtRawBuffer::PjRtRawBuffer() { vtable = &kRawBufferVtable; }
243288

289+
absl::StatusOr<PjRtDeviceEventRef>
290+
PjRtRawBufferInterface::CopyRawHostToDeviceAndReturnEvent(
291+
const void* src, int64_t offset, int64_t transfer_size) {
292+
PJRT_DeviceEvent device_event;
293+
PJRT_Error* error = vtable->copy_raw_host_to_device_and_return_event(
294+
this, src, offset, transfer_size, &device_event);
295+
if (error != nullptr) {
296+
return pjrt::PjrtErrorToStatus(error);
297+
}
298+
return PjRtDeviceEventRef::TakeRef(PjRtDeviceEventPtr(device_event));
299+
}
300+
301+
absl::StatusOr<PjRtDeviceEventRef>
302+
PjRtRawBufferInterface::CopyRawDeviceToHostAndReturnEvent(
303+
void* dst, int64_t offset, int64_t transfer_size) {
304+
PJRT_DeviceEvent device_event;
305+
PJRT_Error* error = vtable->copy_raw_device_to_host_and_return_event(
306+
this, dst, offset, transfer_size, &device_event);
307+
if (error != nullptr) {
308+
return pjrt::PjrtErrorToStatus(error);
309+
}
310+
return PjRtDeviceEventRef::TakeRef(PjRtDeviceEventPtr(device_event));
311+
}
312+
313+
void* PjRtRawBufferInterface::OpaqueDeviceMemoryDataPointer() const {
314+
return vtable->opaque_device_memory_data_pointer(this);
315+
}
316+
317+
void PjRtRawBufferInterface::AddRef() { vtable->inc_ref(this); }
318+
319+
void PjRtRawBufferInterface::DropRef() { vtable->dec_ref(this); }
320+
321+
PjRtMemorySpace* PjRtRawBufferInterface::memory_space() const {
322+
return PjRtMemorySpace::FromC(vtable->get_memory_space(this));
323+
}
324+
325+
void* PjRtRawBufferInterface::GetHostPointer() const {
326+
return vtable->get_host_pointer(this);
327+
}
328+
329+
size_t PjRtRawBufferInterface::GetOnDeviceSizeInBytes() const {
330+
return vtable->get_on_device_size_in_bytes(this);
331+
}
332+
333+
Future<> PjRtRawBufferInterface::CopyRawHostToDevice(const void* src,
334+
int64_t offset,
335+
int64_t transfer_size) {
336+
ASSIGN_OR_RETURN(auto event, CopyRawHostToDeviceAndReturnEvent(
337+
src, offset, transfer_size));
338+
return ConvertEventToFuture(std::move(event));
339+
}
340+
341+
Future<> PjRtRawBufferInterface::CopyRawDeviceToHost(void* dst, int64_t offset,
342+
int64_t transfer_size) {
343+
ASSIGN_OR_RETURN(auto event, CopyRawDeviceToHostAndReturnEvent(
344+
dst, offset, transfer_size));
345+
return ConvertEventToFuture(std::move(event));
346+
}
347+
244348
} // namespace xla

third_party/xla/xla/pjrt/raw_buffer.h

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,30 @@ namespace xla {
4444
class PjRtMemorySpace;
4545
class PjRtBuffer;
4646

47+
class PjRtRawBufferInterface : public PJRT_RawBuffer {
48+
public:
49+
using RemoteSendCallback =
50+
std::function<void(absl::Status status, bool sends_were_enqueued)>;
51+
void AddRef();
52+
void DropRef();
53+
54+
PjRtMemorySpace* memory_space() const;
55+
void* GetHostPointer() const;
56+
size_t GetOnDeviceSizeInBytes() const;
57+
58+
Future<> CopyRawHostToDevice(const void* src, int64_t offset,
59+
int64_t transfer_size);
60+
Future<> CopyRawDeviceToHost(void* dst, int64_t offset,
61+
int64_t transfer_size);
62+
63+
absl::StatusOr<PjRtDeviceEventRef> CopyRawHostToDeviceAndReturnEvent(
64+
const void* src, int64_t offset, int64_t transfer_size);
65+
absl::StatusOr<PjRtDeviceEventRef> CopyRawDeviceToHostAndReturnEvent(
66+
void* dst, int64_t offset, int64_t transfer_size);
67+
68+
void* OpaqueDeviceMemoryDataPointer() const;
69+
};
70+
4771
// Experimental. Don't use unless you know what you're doing.
4872
// A raw buffer is an unsafe API for directly transferring into device
4973
// memory while existing processes are consuming or mutating the same buffer.
@@ -87,23 +111,12 @@ class PjRtRawBuffer : public PJRT_RawBuffer,
87111
virtual Future<> CopyRawDeviceToHost(void* dst, int64_t offset,
88112
int64_t transfer_size) = 0;
89113

90-
private:
91-
static const PJRT_RawBuffer_FunctionTable kRawBufferVtable;
92-
};
93-
94-
class CommonPjRtRawBuffer;
95-
using PjRtRawBufferRef = tsl::RCReference<CommonPjRtRawBuffer>;
96-
97-
// Adds methods common to all implementations of PjRtRawBuffer based on device
98-
// events.
99-
class CommonPjRtRawBuffer : public PjRtRawBuffer {
100-
public:
101114
// Return opaque device memory pointer to the underlying memory.
102115
virtual void* OpaqueDeviceMemoryDataPointer() const = 0;
103116

104117
// Transfers the buffer to a sub-range of the on-device representation.
105118
// offset+transfer_size must be less than GetOnDeviceSizeInBytes. The
106-
// returned future transitions to ready on error, or after the transfer has
119+
// returned event transitions to ready on error, or after the transfer has
107120
// completed.
108121
//
109122
// Note that the underlying driver may have requirements
@@ -114,7 +127,7 @@ class CommonPjRtRawBuffer : public PjRtRawBuffer {
114127

115128
// Transfers a sub-range of the on-device representation of the buffer.
116129
// offset+transfer_size must be less than GetOnDeviceSizeInBytes. The
117-
// returned future transitions to ready on error, or after the transfer has
130+
// returned event transitions to ready on error, or after the transfer has
118131
// completed.
119132
//
120133
// Note that the underlying driver may have requirements
@@ -123,6 +136,15 @@ class CommonPjRtRawBuffer : public PjRtRawBuffer {
123136
virtual absl::StatusOr<PjRtDeviceEventRef> CopyRawDeviceToHostAndReturnEvent(
124137
void* dst, int64_t offset, int64_t transfer_size) = 0;
125138

139+
private:
140+
static const PJRT_RawBuffer_FunctionTable kRawBufferVtable;
141+
};
142+
143+
class CommonPjRtRawBuffer;
144+
using PjRtRawBufferRef = tsl::RCReference<CommonPjRtRawBuffer>;
145+
146+
class CommonPjRtRawBuffer : public PjRtRawBuffer {
147+
public:
126148
// Copies the buffer to a remote device.
127149
// The serialized_descriptor contains metadata about the buffer on the remote
128150
// device. The on_done callback is called when the transfer is complete or

0 commit comments

Comments
 (0)