- ++ , 8 .
?
, 100 , , ( ), 1000, .
:
, , 10 11.
4 × 10 9 , , 2-3 , 4-6 .
. , . , , . , , , . .
:
Daniel Bernstein primegen ( ), , L1- 32 , 90 , 10 11 (234 8K ) Core i5 2410M (2,3 ). ( 2 32 , 10 9 0,49 0,64 .)
, , , 10 11 340 (sniff: -/, , 10 9 2,92 - , - 10 12 10 13 primegen:) , , , 32- GHC.
, , 8 - - , , , . , .
dafis@schwartz:~/Haskell/Repos/arithmoi> time tests/primeCount 100000000000
4118054813
real 0m0.145s
user 0m0.139s
sys 0m0.006s
, 10 ^ 11 32- . , 10 ^ 11 = 12,5 , , 32- Haskell. , .
, . 32- , - . . , L2- ( , L1, , GHC , ).
, , . , 3 , 5 .
, , 10 ^ 11 - 2 ^ 32, .
-, 2, 3 5, 3,3 , , 4 , . , , , .
( , , IOUArray Integer Bool . , 2 10 ...)
.
Int unsafeRead/unsafeWrite . Integer , Int, readArray/writeArray .- 10 , -. ( L2 - ).
- , , 2,
Integer, 10 . ?
:
10 11 . , , -, , , .
, .
-, :
vs <-
mapM
(\ start -> do
let block = (start, start + block_size)
v <- newEmptyMVar
writeChan queue $ do
say $ "New chunk " ++ show block
chunk <- chunk_new block
sieve_top base chunk
c <- chunk_count chunk
putMVar v c
return v
)
(takeWhile (< target) $ iterate (+block_size) base_max)
base_max + k*block_size , , , target.
:
, , , , , , block_size ( 256 L2 512 ) - stdout if prime < 100 then say $ "Sieve " ++ show prime else return ().
() :
chunk_sieve :: Chunk -> Integer -> IO ()
chunk_sieve array prime = do
(min, max) <- getBounds array
let n0 = min `mod` prime
let n1 = if n0 == 0 then min else min - n0 + prime
mapM_
(\ n -> writeArray array n (n == prime))
(takeWhile (<= max) $ iterate (+prime) n1)
, , , , . ( Int), , True, . False True , .
10 9 . 155 (, 292s), block_size 148s, 143s. ,
mapM_
(\ n -> writeArray array n False)
(takeWhile (<= max) $ iterate (+prime) n1)
when (min <= prime && prime <= max) $ writeArray array prime True
131.
. , - ? , ( , Int -overflow), :
chunk_sieve :: Chunk -> Integer -> IO ()
chunk_sieve array prime = do
(min, max) <- getBounds array
let n0 = min `mod` prime
n1 = if n0 == 0 then min else min - n0 + prime
n2 = fromInteger (n1 - min)
mx = fromInteger (max - min)
pr = fromInteger prime
mapM_
(\ n -> unsafeWrite array n False)
(takeWhile (<= mx) $ iterate (+pr) n2)
when (min <= prime && prime <= max) $ writeArray array prime True
96 . , .
takeWhile (<= mx) $ iterate (+pr) n2
GHC , Int . , [n2, n2+pr .. mx] GHC , unboxed Int# s, 37 .
, .
chunk_count :: Chunk -> IO Integer
chunk_count array = do
(min, max) <- getBounds array
work min max 0
where
work i max count = do
b <- readArray array i
let count' = count + if b then 1 else 0
evaluate count'
let i' = i+1
if i' > max
then return count'
else work i' max count'
, .
chunk_count :: Chunk -> IO Integer
chunk_count array = do
(min, max) <- getBounds array
work 0 (fromInteger (max-min)) 0
where
work i max count = do
b <- unsafeRead array i
let count' = count + if b then 1 else 0
evaluate count'
let i' = i+1
if i' > max
then return count'
else work i' max count'
15 . evaluate count' work strict count. else work i' max $! count' evaluate 13 . work ( GHC, ) ,
chunk_count :: Chunk -> IO Integer
chunk_count array = do
(min, max) <- getBounds array
let mx = fromInteger (max-min)
work i !ct
| mx < i = return ct
| otherwise = do
b <- unsafeRead array i
work (i+1) (if b then ct+1 else ct)
work 0 0
6.55 . , say $ "New chunk " ++ show block , , 6.18 .
, 0 . Word ( castIOUArray) popCount, " , ...", 4.25 ; , ,
sieve_top :: Chunk -> Chunk -> IO ()
sieve_top base chunk = work 2
where
work prime = do
chunk_sieve chunk prime
mp <- chunk_next_prime base prime
case mp of
Nothing -> return ()
Just p' -> do
(_,mx) <- getBounds chunk
when (p'*p' <= mx) $ work p'
3,9 . , , , . , : 10 8,5 .
, . , , . , 3,75 , , . ( - - , , , , 4.55 5.3 . , , .)
- Integer GHC ( /, ), , , 10-15%.
. , . , , .