Pratikte rasgele sayı motorlarından hangisi kullanılmalıdır? std :: mt19937?


21

Diyelim ki C ++ <random>olanaklarını pratik bir programda kullanmak istiyorsunuz ("pratik" in bazı tanımları için - buradaki kısıtlamalar bu sorunun bir parçasıdır). Kabaca şöyle bir kod var:

int main(int argc, char **argv) {
    int seed = get_user_provided_seed_value(argc, argv);
    if (seed == 0) seed = std::random_device()();
    ENGINE g(seed);  // TODO: proper seeding?
    go_on_and_use(g);
}

Sorum şu, ne tür kullanmalısın ENGINE?

  • Her zaman söylerdim std::mt19937çünkü yazmak hızlıydı ve isim tanıması vardı. Ancak bu günlerde herkes Mersenne Twister'ın çok ağır ve önbellek dostu olduğunu ve başkalarının yaptığı tüm istatistiksel testleri bile geçmediğini söylüyor.

  • Söylemek isterim std::default_random_engineçünkü bu bariz "varsayılan". Ama platformdan platforma değişip değişmediğini bilmiyorum ve istatistiksel olarak iyi olup olmadığını bilmiyorum.

  • Bugünlerde herkes 64-bit platformunda olduğundan, bunu en azından kullanarak olmalı std::mt19937_64üzerinde std::mt19937?

  • Söylemek isterim pcg64ya da xoroshiro128saygın ve hafif göründüklerinden, ama hiç yoklar <random>.

  • Ben hakkında hiçbir şey bilmiyorum minstd_rand, minstd_rand0, ranlux24, knuth_bmutlaka bir şey için iyi olmalıdır - vs.?

Açıkçası burada bazı rakip kısıtlamalar var.

  • Motor gücü. ( <random>kriptografik olarak güçlü PRNG'leri yoktur, ancak yine de, standartlaştırılmış olanlardan bazıları diğerlerinden daha zayıftır, değil mi?)

  • sizeof motor.

  • Hızı operator().

  • Ekim kolaylığı. mt19937başlaması için çok fazla durumu olduğu için doğru şekilde tohumlanması çok zordur.

  • Kütüphane satıcıları arasında taşınabilirlik. Bir satıcının foo_enginebaşka bir satıcınınkinden farklı numaralar üretmesi foo_engine, bazı uygulamalar için iyi değildir. (Umarım bu belki dışında hiçbir şeyi dışlamaz default_random_engine.)

Tüm bu kısıtlamaları elinizden geldiğince tartarak, nihai "standart kütüphanenin içinde kalmak için en iyi uygulama" cevabı nedir? Sadece kullanmaya devam etmeli miyim std::mt19937yoksa ne?


2
Son noktanıza kadar, tüm standart motor adaptörleri, varsayılan yapılandırılmış olanın ardışık belirli bir çağrısında belirli bir değer döndürmek için belirtilir, bu nedenle taşınabilir olmalıdırlar.
1201ProgramAlarm

Yanıtlar:


15

C ++ Başvurusu , şu anda C ++ tarafından sağlanan tüm rasgele motorları listeler. Bununla birlikte, motor seçimi arzulanan bir şey bırakıyor (örneğin, yüksek kaliteli rastgele jeneratörler listeme bakın ). Örneğin:

  • default_random_engine uygulama tanımlıdır, bu nedenle motorun uygulamanın önemsediği istatistiksel kusurlara sahip olup olmadığı bilinmemektedir.
  • linear_congruential_engineDoğrusal uyumlu jeneratörler uygular. Bununla birlikte, modül asal ve çok büyük olmadıkça (en az 64 bit) kalitesiz olma eğilimindedirler. Ayrıca, modüllerinden daha fazla tohum kabul edemezler.
  • minstd_rand0ve minstd_randsadece yaklaşık 2 ^ 31 tohum kabul. knuth_ba'yı sarar minstd_rand0ve Bays – Durham karıştırmasını yapar.
  • mt19937ve mt19937_64eğer daha iyi başlatılmışlarsa (örneğin, sadece bir değil, std::seed_seqbirden fazla çıktı ile başlatarak) çok daha fazla tohum kabul edebilirler random_device, ancak yaklaşık 2500 bayt durum kullanırlar.
  • ranlux24ve ranlux48yaklaşık 577 bit durum kullanırlar ancak yavaştırlar (bazılarını koruyarak ve diğer yalancı çıktıları atarak çalışırlar).

Bununla birlikte, C ++, rastgele özelliklerini iyileştirmek için başka bir motoru saran iki motora da sahiptir:

  • discard_block_engine verilen rasgele bir motorun bazı çıkışlarını atar.
  • shuffle_order_engine verilen rasgele bir motorun Bays-Durham shuffle'ını uygular.

Örneğin, bir Bays-Durham karıştır sahip olmak, diyelim ki, mümkün mt19937, ranlux24ya da bir özel linear_congruential_engineile shuffle_order_engine. Belki de sarılı motor orijinal olandan daha kaliteli. Ancak, yeni motorun istatistiksel kalitesini test etmeden tahmin etmek zordur .

Bu nedenle, bu tür testler beklemede, mt19937şimdilik C ++ standardındaki en pratik motor gibi görünüyor . Bununla birlikte, C ++ 'ın gelecekteki sürümlerine başka bir rasgele sayı motoru eklemek için en az bir önerinin farkındayım (bkz. C ++ kağıdı P2075 ).


1

Göre C ++ Başvurusu , default_random_engine:

Kütüphane uygulamasının nispeten rahat, yetersiz ve / veya hafif kullanım için en azından kabul edilebilir motor davranışı sağlayan bir jeneratör seçimidir .

Yani için hafif kullanım bir şey hakkında endişe, tohum olması gerekmez default_random_engineile Epoch Time (time(0))ve bu iyi yeterli olurdu;)


Buradaki sorunun taşınabilirlik olduğuna inanıyorum. Varsayılan, iyi performans gösteren bir motor olsa da, başka bir platformda yeniden üretilemeyebilir.
bremen_matt

@bremen_matt Hmm ... Peki, neden "rastgele" bir sayı üretmemiz gerekiyor?
Farbod Ahmadian

2
Test yapmak. Test amacıyla tekrar üretilebilir girdilere ihtiyacınız vardır. Aynı zamanda, bu girdilerin rasgele olmasını isteyebilir veya ihtiyacınız olabilir. Örneğin, çoğu makine öğrenme algoritması, parametrelerin rastgele başlatıldığını varsayar. Ransac, CNNs, DNNs, ... birçok algoritma rastgele parametreler gerektirir.
bremen_matt
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.