前提
Pythonを使ってソーシャルゲームのガチャのシミュレーションを行いたいのですが、単純に random.random()
をfor文で繰り返し行うのでは1億回の計算で47秒かかってしまいました。
更に精度を上げたいですが、これ以上は10億回で10分、100億回で100分と、指数関数的に計算時間が増えてしまうため、なにか良い案は無いかと思い質問させていただきました。
実現したいこと
random.random()
の繰り返しによるソーシャルゲームのガチャのシミュレーションプログラムの計算速度向上。
何かライブラリを使用して高速化する案、プログラムの無駄を指摘して高速化する案などをお答えいただきたいです。
せめて1000億回程度を数分以内に行えるようにと考えていますが、早ければ早いほど良いです。
シミュレーションのコード
Python
1from random import random 2 3from tqdm import tqdm 4 5 6RATE4 = 0.051 7RATE4UP = 0.511 8RATE5 = 0.006 9RATE5UP = 0.324 10 11 12class Wish(): 13 def __init__(self) -> None: 14 self.count4 = 0 15 self.count5 = 0 16 17 def wish(self): 18 return self.get_rarity() 19 20 def get_rarity(self): 21 self.set_th() 22 23 th = random() 24 if th < self.th5: 25 self.count4 += 1 26 self.count5 = 0 27 return 5 28 elif th < self.th4: 29 self.count4 = 0 30 self.count5 += 1 31 return 4 32 else: 33 self.count4 += 1 34 self.count5 += 1 35 return 3 36 37 def set_th(self): 38 if self.count5 < 75: 39 self.th5 = RATE5 40 elif self.count5 < 89: 41 self.th5 = RATE5UP 42 else: 43 self.th5 = 1 44 45 if self.count4 < 8: 46 self.th4 = self.th5 + RATE4 47 elif self.count4 < 9: 48 self.th4 = self.th5 + RATE4UP 49 else: 50 self.th4 = 1 51 52 53wish = Wish() 54 55count5 = 0 56count4 = 0 57 58COUNT = 100000000 59for _ in tqdm(range(COUNT)): 60 result = wish.wish() 61 if result == 5: 62 count5 += 1 63 elif result == 4: 64 count4 += 1 65 66print('★4: ' + str(count4 * 100 / COUNT) + '%') 67print('★5: ' + str(count5 * 100 / COUNT) + '%') 68
出力される値は毎回ほぼ同じですがどういった意図がありますか?このコードにどんな挙動、及び結果を期待しますか?
場合によっては、random.choices() や random.sample() あたりが使えそうです。それを非同期 (asyncio) で回せばそれなりに速くなるような気がします。
追記:よくよく考えたら非同期にするとタスクを一時的に保存しておくメモリが足りなくなりますね。numpy 使っても条件は変わらないし、下のお二方の言う通りコンパイル言語を使うのが現実的な気がします。
他のプログラミング言語(C, C++, Rust などのコンパイラ)で実装してみてはどうでしょうか。例えば、質問にある Python コードでは80秒、Golang version 1.20pre では 2.4秒でした。
速くしたいのであれば、コンパイル言語を使ってみるのはどうでしょうか?
