11#include " ../utils_op.h"
2- #include " musa_fill_functor.h"
2+ #include " mu/device/musa_memcpy.h"
3+
4+ #include < algorithm>
5+ #include < musa_runtime.h>
6+ #include < vector>
7+
38#include " tensorflow/core/framework/op_kernel.h"
49#include " tensorflow/core/framework/register_types.h"
510#include " tensorflow/core/framework/tensor.h"
@@ -12,6 +17,22 @@ namespace musa {
1217
1318namespace {
1419
20+ extern " C" {
21+ void LaunchMusaFill_float (float * out, float value, int64_t n,
22+ musaStream_t stream);
23+ void LaunchMusaFill_double (double * out, double value, int64_t n,
24+ musaStream_t stream);
25+ void LaunchMusaFill_int32 (int32* out, int32 value, int64_t n,
26+ musaStream_t stream);
27+ void LaunchMusaFill_int64 (int64* out, int64 value, int64_t n,
28+ musaStream_t stream);
29+ void LaunchMusaFill_half (Eigen::half* out, Eigen::half value, int64_t n,
30+ musaStream_t stream);
31+ void LaunchMusaFill_bfloat16 (Eigen::bfloat16* out, Eigen::bfloat16 value,
32+ int64_t n, musaStream_t stream);
33+ void LaunchMusaFill_bool (bool * out, bool value, int64_t n, musaStream_t stream);
34+ }
35+
1536template <typename T, typename ... Rest>
1637struct is_any : std::false_type {};
1738
@@ -23,31 +44,88 @@ struct is_any<T, First, Rest...>
2344 : std::integral_constant<bool , std::is_same<T, First>::value ||
2445 is_any<T, Rest...>::value> {};
2546
26- // template <typename T>
27- // Status MusaFillCall(Tensor* out, T value, OpKernelContext* context) {
28- // mFill op;
29- // mHandle& h = GetHandleByCtx(context);
30- // auto out_mt = CreateMTensor(*out);
31-
32- // if (is_any<T, int8, int16, int, int64, uint8, uint16, uint32, uint64,
33- // bool>::value) {
34- // if (mStatus::SUCCESS != op.SetValue(static_cast<int64_t>(value))) {
35- // return errors::Internal("mtdnn set value (int) error!");
36- // }
37- // } else if (is_any<T, float, double, Eigen::half, Eigen::bfloat16>::value) {
38- // if (mStatus::SUCCESS != op.SetValue(static_cast<double>(value))) {
39- // return errors::Internal("mtdnn set value (float) error!");
40- // }
41- // } else {
42- // return errors::Unimplemented("Data type not supported in MTGPU Fill.");
43- // }
44-
45- // if (mStatus::SUCCESS != op.Run(h, out_mt)) {
46- // return errors::Internal("mtdnn run op error!");
47- // }
48-
49- // return OkStatus();
50- // }
47+ template <typename T>
48+ Status LaunchFillKernel (T* out, T value, int64_t n, musaStream_t stream);
49+
50+ #define DEFINE_FILL_LAUNCHER (T, suffix ) \
51+ template <> \
52+ Status LaunchFillKernel<T>(T* out, T value, int64_t n, musaStream_t stream) { \
53+ LaunchMusaFill_##suffix (out, value, n, stream); \
54+ musaError_t err = musaGetLastError (); \
55+ if (err != musaSuccess) { \
56+ return errors::Internal (" MUSA Fill kernel launch failed: " , \
57+ musaGetErrorString (err)); \
58+ } \
59+ return OkStatus (); \
60+ }
61+
62+ DEFINE_FILL_LAUNCHER (float , float )
63+ DEFINE_FILL_LAUNCHER (double , double )
64+ DEFINE_FILL_LAUNCHER (int32, int32)
65+ DEFINE_FILL_LAUNCHER (int64, int64)
66+ DEFINE_FILL_LAUNCHER (Eigen::half, half)
67+ DEFINE_FILL_LAUNCHER (Eigen::bfloat16, bfloat16)
68+ DEFINE_FILL_LAUNCHER (bool , bool )
69+
70+ #undef DEFINE_FILL_LAUNCHER
71+
72+ bool IsDeviceReadablePointer (const void * ptr) {
73+ musaPointerAttributes attributes;
74+ musaError_t attr_err = musaPointerGetAttributes (&attributes, ptr);
75+ if (attr_err == musaSuccess) {
76+ return attributes.type == musaMemoryTypeDevice ||
77+ attributes.type == musaMemoryTypeManaged;
78+ }
79+
80+ // Pageable host memory is reported as unregistered on some MUSA versions.
81+ musaGetLastError ();
82+ return false ;
83+ }
84+
85+ template <typename T>
86+ Status ReadVectorInputToHost (OpKernelContext* context, int input_index,
87+ std::vector<T>* values) {
88+ const Tensor& tensor = context->input (input_index);
89+ values->resize (tensor.NumElements ());
90+ if (values->empty ()) {
91+ return OkStatus ();
92+ }
93+
94+ const T* input_data = tensor.flat <T>().data ();
95+ if (IsDeviceReadablePointer (input_data)) {
96+ mStatus copy_status =
97+ MusaMemcpyD2H (values->data (), input_data, tensor.TotalBytes ());
98+ if (copy_status != mStatus ::SUCCESS ) {
99+ return errors::Internal (" MUSA Fill failed to copy input " , input_index,
100+ " to host." );
101+ }
102+ } else {
103+ std::copy (input_data, input_data + values->size (), values->data ());
104+ }
105+ return OkStatus ();
106+ }
107+
108+ template <typename T>
109+ Status ReadScalarInputToHost (OpKernelContext* context, int input_index,
110+ T* value) {
111+ const Tensor& tensor = context->input (input_index);
112+ if (tensor.NumElements () < 1 ) {
113+ return errors::InvalidArgument (" MUSA Fill input " , input_index,
114+ " must contain a scalar value." );
115+ }
116+
117+ const T* input_data = tensor.flat <T>().data ();
118+ if (IsDeviceReadablePointer (input_data)) {
119+ mStatus copy_status = MusaMemcpyD2H (value, input_data, sizeof (T));
120+ if (copy_status != mStatus ::SUCCESS ) {
121+ return errors::Internal (" MUSA Fill failed to copy scalar input " ,
122+ input_index, " to host." );
123+ }
124+ } else {
125+ *value = input_data[0 ];
126+ }
127+ return OkStatus ();
128+ }
51129
52130} // namespace
53131
@@ -78,21 +156,29 @@ class MusaFillOp : public MusaOpKernel {
78156 errors::InvalidArgument (" value must represent a scalar, got shape " ,
79157 Tvalue.shape ().DebugString ()));
80158
81- auto dims_vec = Tdims.flat <Index>();
159+ std::vector<Index> host_dims;
160+ OP_REQUIRES_OK (context, ReadVectorInputToHost<Index>(context, 0 , &host_dims));
161+
82162 TensorShape shape;
83- OP_REQUIRES_OK (context, TensorShapeUtils::MakeShape (
84- reinterpret_cast < const Index*>(dims_vec. data ()) ,
85- dims_vec .size (), &shape));
163+ OP_REQUIRES_OK (
164+ context ,
165+ TensorShapeUtils::MakeShape (host_dims. data (), host_dims .size (), &shape));
86166
87167 Tensor* out = nullptr ;
88168 OP_REQUIRES_OK (context, context->allocate_output (0 , shape, &out));
89169
90170 if (shape.num_elements () == 0 ) return ;
91171
92- auto out_mt = CreateMTensor (*out);
93- OP_REQUIRES_OK (
94- context,
95- MusaFillCall (&out_mt, static_cast <T*>(Tvalue.data ())[0 ], context));
172+ musaStream_t stream = GetMusaStreamByCtx (context);
173+ OP_REQUIRES (context, stream != nullptr ,
174+ errors::Internal (" MUSA stream is unavailable for Fill" ));
175+
176+ T host_value;
177+ OP_REQUIRES_OK (context, ReadScalarInputToHost<T>(context, 1 , &host_value));
178+
179+ OP_REQUIRES_OK (context,
180+ LaunchFillKernel<T>(out->flat <T>().data (), host_value,
181+ shape.num_elements (), stream));
96182 }
97183};
98184
0 commit comments