|
21 | 21 | GeneralizedTensor = TypeVar("GeneralizedTensor", torch.Tensor, np.ndarray) |
22 | 22 |
|
23 | 23 |
|
24 | | -def fp32_accum_wrapper(func): |
25 | | - def wrapper(tensor_to_sum, ret_tensor): |
26 | | - half = tensor_to_sum.dtype == np.float16 |
27 | | - if half: |
28 | | - tensor_to_sum = tensor_to_sum.astype(np.float32) |
29 | | - retval = func(tensor_to_sum, ret_tensor) |
30 | | - if half: |
31 | | - retval = retval.astype(np.float16) |
32 | | - return retval |
33 | | - |
34 | | - return wrapper |
35 | | - |
36 | | - |
37 | | -@fp32_accum_wrapper |
38 | | -def sum_like(tensor_to_sum, ref_tensor): |
39 | | - """Warning: may modify tensor_to_sum""" |
40 | | - if ref_tensor.size == 1: |
41 | | - return tensor_to_sum.sum() |
42 | | - |
43 | | - for dim, size in enumerate(ref_tensor.shape): |
44 | | - if size == 1: |
45 | | - if isinstance(tensor_to_sum, np.ndarray): |
46 | | - tensor_to_sum = tensor_to_sum.sum(dim, keepdims=True) |
47 | | - else: |
48 | | - tensor_to_sum = tensor_to_sum.sum(dim, keepdim=True) |
49 | | - return tensor_to_sum |
50 | | - |
51 | | - |
52 | 24 | class ReferenceBackendType(Enum): |
53 | 25 | NUMPY = "numpy" |
54 | 26 | TORCH = "torch" |
@@ -79,6 +51,46 @@ def _reciprocal(self, tensor: GeneralizedTensor) -> GeneralizedTensor: |
79 | 51 | return np.reciprocal(tensor) |
80 | 52 | return torch.reciprocal(tensor) |
81 | 53 |
|
| 54 | + def _sum_like(self, tensor_to_sum: GeneralizedTensor, ref_tensor: GeneralizedTensor): |
| 55 | + """Warning: may modify tensor_to_sum""" |
| 56 | + if self.backend is np: |
| 57 | + half = tensor_to_sum.dtype == np.float16 |
| 58 | + if half: |
| 59 | + tensor_to_sum = tensor_to_sum.astype(np.float32) |
| 60 | + retval = self._sum_like_fp32(tensor_to_sum, ref_tensor) |
| 61 | + if half: |
| 62 | + retval = retval.astype(np.float16) |
| 63 | + return retval |
| 64 | + |
| 65 | + half = tensor_to_sum.dtype == torch.float16 |
| 66 | + if half: |
| 67 | + tensor_to_sum = tensor_to_sum.type(torch.float32) |
| 68 | + retval = self._sum_like_fp32(tensor_to_sum, ref_tensor) |
| 69 | + if half: |
| 70 | + retval = retval.type(torch.float16) |
| 71 | + return retval |
| 72 | + |
| 73 | + def _sum_like_fp32(self, tensor_to_sum: GeneralizedTensor, ref_tensor: GeneralizedTensor): |
| 74 | + """Warning: may modify tensor_to_sum""" |
| 75 | + if self.backend is np: |
| 76 | + n_elements = ref_tensor.size |
| 77 | + if n_elements == 1: |
| 78 | + return tensor_to_sum.sum() |
| 79 | + |
| 80 | + for dim, size in enumerate(ref_tensor.shape): |
| 81 | + if size == 1: |
| 82 | + tensor_to_sum = tensor_to_sum.sum(dim, keepdims=True) |
| 83 | + return tensor_to_sum |
| 84 | + |
| 85 | + n_elements = ref_tensor.numel() |
| 86 | + if n_elements == 1: |
| 87 | + return tensor_to_sum.sum() |
| 88 | + |
| 89 | + for dim, size in enumerate(ref_tensor.shape): |
| 90 | + if size == 1: |
| 91 | + tensor_to_sum = tensor_to_sum.sum(dim, keepdim=True) |
| 92 | + return tensor_to_sum |
| 93 | + |
82 | 94 | def forward( |
83 | 95 | self, input_: GeneralizedTensor, input_low: GeneralizedTensor, input_range: GeneralizedTensor, levels: int |
84 | 96 | ) -> GeneralizedTensor: |
@@ -114,12 +126,12 @@ def backward( |
114 | 126 | output = self.forward(input_, input_low, input_range, levels) |
115 | 127 | err = (output - input_) * self._reciprocal(input_range * range_sign) |
116 | 128 | grad_range = grad_output * (err * mask_in + range_sign * (level_low / level_high) * mask_lo + mask_hi) |
117 | | - grad_range = sum_like(grad_range, input_range) |
| 129 | + grad_range = self._sum_like(grad_range, input_range) |
118 | 130 |
|
119 | 131 | grad_input = grad_output * mask_in |
120 | 132 |
|
121 | 133 | grad_low = grad_output * (mask_hi + mask_lo) |
122 | | - grad_low = sum_like(grad_low, input_low) |
| 134 | + grad_low = self._sum_like(grad_low, input_low) |
123 | 135 | return [grad_input, grad_low, grad_range] |
124 | 136 |
|
125 | 137 | def tune_range( |
|
0 commit comments