Either sort only values or sort values by keys.
(
size,
axis_mul_before,
axis_mul_after,
is_ascend,
keys,
keys_swap,
values=None,
values_swap=None,
)
| 181 | |
| 182 | |
| 183 | def _sort_common( |
| 184 | size, |
| 185 | axis_mul_before, |
| 186 | axis_mul_after, |
| 187 | is_ascend, |
| 188 | keys, |
| 189 | keys_swap, |
| 190 | values=None, |
| 191 | values_swap=None, |
| 192 | ): |
| 193 | """Either sort only values or sort values by keys.""" |
| 194 | |
| 195 | ## This function performs a multi-level mergesort |
| 196 | ## For blocks of length <= block_size, it does odd-even transpose sort |
| 197 | ## in GPU shared memory |
| 198 | ## For intermediate block sizes (>block_size, < max_threads * thread_work) |
| 199 | ## it uses the mergpath algorthim https://arxiv.org/abs/1406.2628 |
| 200 | ## to merge blocks in parallel |
| 201 | ## At some point, the size of the blocks to be merged is too big for max_threads |
| 202 | ## and we switch to using a dual-level mergepath where the outer mergepath |
| 203 | ## finds the start/end locations of the inner mergepath so that we can split |
| 204 | ## the merge into more blocks |
| 205 | |
| 206 | target = tvm.target.Target.current(allow_none=False) |
| 207 | max_threads = int(target.attrs["max_num_threads"]) |
| 208 | is_webgpu = "webgpu" in str(target) |
| 209 | target_dtype = "int32" if is_webgpu else "int64" |
| 210 | nthread_by = axis_mul_before * axis_mul_after |
| 211 | nthread_tx = max_threads |
| 212 | nthread_bx = ceil_div(size, nthread_tx) |
| 213 | |
| 214 | def compare(a, b): |
| 215 | """Compare a and b in proper ascending or descending order""" |
| 216 | if is_ascend: |
| 217 | out = a <= b |
| 218 | else: |
| 219 | out = b <= a |
| 220 | return out |
| 221 | |
| 222 | # Sort the lower levels of the merge using odd-even sort, it's fast for small inputs |
| 223 | lower_lim = ceil_log2(block_size) |
| 224 | |
| 225 | _odd_even_sort( |
| 226 | size, |
| 227 | axis_mul_before * axis_mul_after, |
| 228 | 1, |
| 229 | is_ascend, |
| 230 | keys, |
| 231 | keys_swap, |
| 232 | values, |
| 233 | values_swap, |
| 234 | ) |
| 235 | |
| 236 | upper_lim = ceil_log2(size) |
| 237 | |
| 238 | def get_merge_begin(source, base_idx, aCount, bCount, aStart, bStart, diag, first, last): |
| 239 | max_val = tvm.te.max(0, diag - bCount) |
| 240 | min_val = tvm.te.min(diag, aCount) |
no test coverage detected
searching dependent graphs…