Since you are only looking for pair of cards, you have only 1128
possible pairs (without replacement), so you could generate all pairs and then pick random cards from this set:
from itertools import combinations
# There may be a better way to generate all possible pairs in numpy,
# but I am not aware of and this is pretty fast for this size
all_pairs = np.array(list(combinations(range(12 * 4), 2)))
cards = all_pairs[np.random.randint(all_pairs.shape[0], size = N_PAIRS), :]
Where N_PAIRS
is the number of pairs you want.
Benchmarks:
In [55]: # Input params
...: N = 1000000 # Number of queries
...: M = 2 # Number of cards to be picked
...:
...: def original_app(N,M):
...: out = np.empty((N,2),dtype=int)
...: for i in range(N):
...: out[i] = np.random.choice(12*4,M, replace=False)
...: return out
...:
...: def vectorized_app(N,M):
...: return np.argpartition(np.random.rand(N,12*4),M,axis=1)[:,:M]
...:
...: def itertools_app(N,M):
...: all_pairs = np.array(list(combinations(range(12 * 4), M)))
...: return all_pairs[np.random.randint(all_pairs.shape[0], size = N), :]
In [46]: %timeit original_app(N,M)
1 loops, best of 3: 10.8 s per loop
In [47]: %timeit vectorized_app(N,M)
1 loops, best of 3: 618 ms per loop
In [48]: %timeit itertools_app(N,M)
10 loops, best of 3: 24.8 ms per loop
This method is really fast when M
is very small, as M
gets bigger, the number of combinations increases exponentially, and thus even creating the all_pairs
array is not possible (already with M = 5
you have ~1700000 possible combinations).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…