Allocates an integer number of threads across datasets based on weights. The final array sums to `n`, but each element is no less than 1. If `n` is None, then every dataset is assigned a value of AUTOTUNE.
(n: Optional[int], weights: np.ndarray)
| 809 | |
| 810 | |
| 811 | def allocate_threads(n: Optional[int], weights: np.ndarray): |
| 812 | """ |
| 813 | Allocates an integer number of threads across datasets based on weights. |
| 814 | |
| 815 | The final array sums to `n`, but each element is no less than 1. If `n` is None, then every dataset is assigned a |
| 816 | value of AUTOTUNE. |
| 817 | """ |
| 818 | if n is None: |
| 819 | return np.array([tf.data.AUTOTUNE] * len(weights)) |
| 820 | |
| 821 | assert np.all(weights >= 0), "Weights must be non-negative" |
| 822 | assert len(weights) <= n, "Number of threads must be at least as large as length of weights" |
| 823 | weights = np.array(weights) / np.sum(weights) |
| 824 | |
| 825 | allocation = np.zeros_like(weights, dtype=int) |
| 826 | while True: |
| 827 | # Give the remaining elements that would get less than 1 a 1 |
| 828 | mask = (weights * n < 1) & (weights > 0) |
| 829 | if not mask.any(): |
| 830 | break |
| 831 | n -= mask.sum() |
| 832 | allocation += mask.astype(int) |
| 833 | |
| 834 | # Recompute the distribution over the remaining elements |
| 835 | weights[mask] = 0 |
| 836 | weights = weights / weights.sum() |
| 837 | |
| 838 | # Allocate the remaining elements |
| 839 | fractional, integral = np.modf(weights * n) |
| 840 | allocation += integral.astype(int) |
| 841 | n -= integral.sum() |
| 842 | for i in np.argsort(fractional)[::-1][: int(n)]: |
| 843 | allocation[i] += 1 |
| 844 | |
| 845 | return allocation |
| 846 | |
| 847 | |
| 848 | def decode_and_resize( |
no outgoing calls
no test coverage detected