Thrown when an array cannot be allocated
| 115 | |
| 116 | @_display_as_base |
| 117 | class _ArrayMemoryError(MemoryError): |
| 118 | """ Thrown when an array cannot be allocated""" |
| 119 | def __init__(self, shape, dtype): |
| 120 | self.shape = shape |
| 121 | self.dtype = dtype |
| 122 | |
| 123 | @property |
| 124 | def _total_size(self): |
| 125 | num_bytes = self.dtype.itemsize |
| 126 | for dim in self.shape: |
| 127 | num_bytes *= dim |
| 128 | return num_bytes |
| 129 | |
| 130 | @staticmethod |
| 131 | def _size_to_string(num_bytes): |
| 132 | """ Convert a number of bytes into a binary size string """ |
| 133 | |
| 134 | # https://en.wikipedia.org/wiki/Binary_prefix |
| 135 | LOG2_STEP = 10 |
| 136 | STEP = 1024 |
| 137 | units = ['bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB'] |
| 138 | |
| 139 | unit_i = max(num_bytes.bit_length() - 1, 1) // LOG2_STEP |
| 140 | unit_val = 1 << (unit_i * LOG2_STEP) |
| 141 | n_units = num_bytes / unit_val |
| 142 | del unit_val |
| 143 | |
| 144 | # ensure we pick a unit that is correct after rounding |
| 145 | if round(n_units) == STEP: |
| 146 | unit_i += 1 |
| 147 | n_units /= STEP |
| 148 | |
| 149 | # deal with sizes so large that we don't have units for them |
| 150 | if unit_i >= len(units): |
| 151 | new_unit_i = len(units) - 1 |
| 152 | n_units *= 1 << ((unit_i - new_unit_i) * LOG2_STEP) |
| 153 | unit_i = new_unit_i |
| 154 | |
| 155 | unit_name = units[unit_i] |
| 156 | # format with a sensible number of digits |
| 157 | if unit_i == 0: |
| 158 | # no decimal point on bytes |
| 159 | return '{:.0f} {}'.format(n_units, unit_name) |
| 160 | elif round(n_units) < 1000: |
| 161 | # 3 significant figures, if none are dropped to the left of the . |
| 162 | return '{:#.3g} {}'.format(n_units, unit_name) |
| 163 | else: |
| 164 | # just give all the digits otherwise |
| 165 | return '{:#.0f} {}'.format(n_units, unit_name) |
| 166 | |
| 167 | def __str__(self): |
| 168 | size_str = self._size_to_string(self._total_size) |
| 169 | return ( |
| 170 | "Unable to allocate {} for an array with shape {} and data type {}" |
| 171 | .format(size_str, self.shape, self.dtype) |
| 172 | ) |
no outgoing calls