Since you are looking for only a pair of cards, you have only 1128 possible pairs (without replacement), so you can generate all pairs, and then select random cards from this set:
from itertools import combinations
Where N_PAIRS is the number of pairs you want.
Landmarks:
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 very fast when M very small, as M increases, the number of combinations increases exponentially, and therefore even creating an all_pairs array all_pairs impossible (already with M = 5 you have ~ 1,700,000 possible combinations).
source share