Ответ 1
Одна проблема с использованием np.random.randint
заключается в том, что он генерирует 64-битные целые числа, тогда как numpy np.bool
dtype использует только 8 бит для представления каждого логического значения. Поэтому вы выделяете промежуточный массив размером 8x больше необходимого.
Обходной путь, который позволяет избежать промежуточных 64-разрядных типов, состоит в том, чтобы сгенерировать строку случайных байтов, используя np.random.bytes
, которая может быть преобразована в массив из 8-битных целых чисел, используя np.fromstring
. Эти целые числа затем могут быть преобразованы в логические значения, например, путем проверки, меньше ли они 255 * p, где p - желаемая вероятность того, что каждый элемент имеет значение True
:
import numpy as np
def random_bool(shape, p=0.5):
n = np.prod(shape)
x = np.fromstring(np.random.bytes(n), np.uint8, n)
return (x < 255 * p).reshape(shape)
Benchmark:
In [1]: shape = 1200, int(2E6)
In [2]: %timeit random_bool(shape)
1 loops, best of 3: 12.7 s per loop
Одно важное предостережение состоит в том, что вероятность будет округлена до ближайшего кратного 1/256 (для точного кратного 1/256, такого как p = 1/2, это не должно влиять на точность).
Обновление:
Еще более быстрый метод заключается в том, чтобы использовать тот факт, что вам нужно всего лишь создать один случайный бит на 0 или 1 в вашем выходном массиве. Поэтому вы можете создать случайный массив из 8-битных целых чисел размером 1/8 размера конечного вывода, а затем преобразовать его в np.bool
с помощью np.unpackbits
:
def fast_random_bool(shape):
n = np.prod(shape)
nb = -(-n // 8) # ceiling division
b = np.fromstring(np.random.bytes(nb), np.uint8, nb)
return np.unpackbits(b)[:n].reshape(shape).view(np.bool)
Например:
In [3]: %timeit fast_random_bool(shape)
1 loops, best of 3: 5.54 s per loop