私は素数をテストする2つの方法があります。そのうちの1つはisPrime
と呼ばれ、もう1つはisBigPrime
です。私がもともと望んでいたのは、私がすでに計算した "小さい"素数で "大きな"素数をテストして、テストがより速くなるようにすることです。私は1700〜3E6とSQRT(3E6)までの素数を持っていると思った私は、これら2つのアルゴリズムを比較するために、それらの合計を取ったので、私は、上限として1700を選択したハスケルを用いたプライムテストのパフォーマンス
intSqrt :: Integer -> Integer
intSqrt n = round $ sqrt $ fromIntegral n
isPrime' :: Integer->Integer -> Bool
isPrime' 1 m = False
isPrime' n m = do
if (m > (intSqrt n))
then True
else if (rem n (m+1) == 0)
then False
else do isPrime' n (m+1)
isPrime :: Integer -> Bool
isPrime 2 = True
isPrime 3 = True
isPrime n = isPrime' n 1
isBigPrime' :: Integer ->Int ->Bool
isBigPrime' n i =
if ((smallPrimes !! i) > intSqrt n)
then True
else if (rem n (smallPrimes !! i) == 0)
then False
else do isBigPrime' n (i+1)
smallPrimes = [2,3, List of Primes until 1700]
--Start at 1 because we only go through uneven numbers
isBigPrime n = isBigPrime' n 1
primes m = [2]++[k | k <- [3,5..m], isPrime k]
bigPrimes m = smallPrimes ++ [k | k <- [1701,1703..m], isBigPrime k]
main = do
print $ (sum $ [Enter Method] 2999999)
:ここに私の実装があります。私はbigPrimes
が速くなると思ったのですが、最初はそれほど計算が少ないので、とはあまりにも大きすぎませんが、とにかく頭のスタートがあります。しかし、驚いたことにbigPrimes
はprimes
よりも遅かった。ここでの結果は以下のとおりです。primes
Performance counter stats for './p10':
16768,627686 task-clock (msec) # 1,000 CPUs utilized
58 context-switches # 0,003 K/sec
1 cpu-migrations # 0,000 K/sec
6.496 page-faults # 0,387 K/sec
53.416.641.157 cycles # 3,186 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
160.411.056.099 instructions # 3,00 insns per cycle
34.512.352.987 branches # 2058,150 M/sec
10.673.742 branch-misses # 0,03% of all branches
16,773316435 seconds time elapsed
については
、それはケースだろう、なぜbigPrimes
Performance counter stats for './p10':
19111,667046 task-clock (msec) # 0,999 CPUs utilized
259 context-switches # 0,014 K/sec
3 cpu-migrations # 0,000 K/sec
6.278 page-faults # 0,328 K/sec
61.027.453.425 cycles # 3,193 GHz
<not supported> stalled-cycles-frontend
<not supported> stalled-cycles-backend
198.207.905.034 instructions # 3,25 insns per cycle
34.632.138.061 branches # 1812,094 M/sec
106.102.114 branch-misses # 0,31% of all branches
19,126843560 seconds time elapsed
のために私は思っていました。私はprimes!!n
を使用してbigPrimes
をいくらか遅くすることを疑っていますが、私は完全にはわかりません。
あなたの統計を見ると、私に飛びつく最も大きな違いは「ブランチミス」です。小さな素数の関数は '' '' 10.673.742ブランチミス#0,03%of all branches'''を持ち、ビッグ素数の関数は '' '106.102.114ブランチミス#0,31%of all branches '' '。あなたの大きな素数関数は、あなたの小さな素数関数の分だけブランチを10倍誤予測します。それはあなたにいくつかの減速を引き起こす可能性があります。しかし、それはおそらく全体の物語ではないという大きな素数の場合でもミス率は十分に小さいですが、 – Rainbacon
特定の数値が素数であるかどうかを確認することに興味があるならば、はるかに良い方法があります。例えば、 – user2297560
"pがnの平方根よりも大きい"というのは、 "pの平方根がnより大きい"と同等であるが、後者は整数の乗算と比較しか必要としないが、前者はるかに多くのCPU作業が必要です。 – Ingo