Dispatcher to dispatch sampling op.
| 28 | |
| 29 | @expr_functor.mutator |
| 30 | class SamplingDispatcher(BackendDispatcher): |
| 31 | """Dispatcher to dispatch sampling op.""" |
| 32 | |
| 33 | def visit_call_(self, call: relax.Call) -> relax.Expr: |
| 34 | if not isinstance(call.op, Op): |
| 35 | return super().visit_call_(call) |
| 36 | |
| 37 | if call.op.name == "relax.multinomial_from_uniform": |
| 38 | from tvm.relax.backend.gpu_generic import ( # pylint: disable=import-outside-toplevel |
| 39 | generic_get_sample_index, |
| 40 | gpu_multinomial_from_uniform, |
| 41 | ) |
| 42 | |
| 43 | prob, uniform_sample, sample_indices = call.args |
| 44 | tgt = self._get_target(call.struct_info) |
| 45 | dtype = call.attrs.dtype |
| 46 | _, prob_dtype = self.get_shape_dtype(prob) |
| 47 | sample_shape, sample_dtype = self.get_shape_dtype(uniform_sample) |
| 48 | sample_indices_shape, sample_indices_dtype = self.get_shape_dtype(sample_indices) |
| 49 | |
| 50 | if len(sample_shape) != 2 or sample_shape[1] != 1: |
| 51 | raise ValueError("uniform_sample should be a 2D tensor with shape (N, 1)") |
| 52 | |
| 53 | if len(sample_indices_shape) != 2 or sample_indices_shape[1] != 1: |
| 54 | raise ValueError("sample_indices should be a 2D tensor with shape (N, 1)") |
| 55 | |
| 56 | if self.is_gpu_target(tgt): |
| 57 | gv = self.builder_.add_func( |
| 58 | gpu_multinomial_from_uniform( |
| 59 | prob_dtype, sample_dtype, sample_indices_dtype, dtype |
| 60 | ), |
| 61 | "gpu_multinomial_from_uniform", |
| 62 | ) |
| 63 | return relax.call_tir( |
| 64 | gv, |
| 65 | [prob, uniform_sample, sample_indices], |
| 66 | out_sinfo=call.struct_info, |
| 67 | ) |
| 68 | else: |
| 69 | cumsum_prob = relax.op.cumsum(prob, axis=1, dtype=prob_dtype, exclusive=False) |
| 70 | gv = self.builder_.add_func( |
| 71 | generic_get_sample_index(prob_dtype, sample_dtype, sample_indices_dtype, dtype), |
| 72 | "get_sample_index", |
| 73 | ) |
| 74 | return relax.call_tir( |
| 75 | gv, |
| 76 | [cumsum_prob, uniform_sample, sample_indices], |
| 77 | out_sinfo=call.struct_info, |
| 78 | ) |
| 79 | |
| 80 | return super().visit_call_(call) |
| 81 | |
| 82 | |
| 83 | @module_pass(opt_level=0, name="DispatchSampling") |
no outgoing calls
no test coverage detected
searching dependent graphs…