2016-09-09 3 views
1

整数の行列をArrayArray#として実装しようとしています。それは私に速いswapLinesオペレーションを与えるはずです。それはいくつかの整数をコピーするのではなく、メモリ内にネイティブポインタを書き込むだけです。すべてのタイプが解除されているため、メモリの方向はVector (Unboxed.Vector Int)より少なくする必要があります。Segfault in ArrayArray#

小さな行列の場合はうまく動作しますが、サイズを大きくするとセグメンテーションが失敗します。

{-# language CPP #-} 

-- imports 

#include "MachDeps.h" 

そしてコードで:

case newByteArray# (SIZEOF_HSINT# *# colCount) s of 

あなたはMachDeps.hhereの内容を見つけることができますあなたがTODO sizeof Intを行う場合、それは大丈夫と思われる、crashBigMatrixを実行している

{-# LANGUAGE MagicHash, UnboxedTuples #-} 

module Matrix where 

import Control.Monad.ST 
import GHC.ST 
import GHC.Exts 
import GHC.Prim 
import GHC.Magic(runRW#) 

data Matrix = Matrix ArrayArray# -- lifts the array from # to * 
data MutableMatrix s = MutableMatrix (MutableArrayArray# s) 

generateLine :: MutableByteArray# s -> Int# -> Int# -> Int# -> (Int -> Int -> Int) -> State# s -> State# s 
generateLine mbar curLine curCol colCount genFunc s = 
    case curCol ==# colCount of 
    0# -> case genFunc (I# curLine) (I# curCol) of 
     (I# x) -> generateLine mbar curLine (curCol +# 1#) colCount genFunc (writeIntArray# mbar curCol x s) -- if curCol is replaced by 0#, doesn't crash 
    _ -> s 

initLines :: MutableArrayArray# s -> Int# -> Int# -> Int# -> (Int -> Int -> Int) -> State# s -> State# s 
initLines mat curLine lineCount colCount genFunc s = 
    case curLine ==# lineCount of 
    1# -> s 
    0# -> case newByteArray# (4# *# colCount) s of -- TODO sizeof Int ? 
     (# s1, mbar #) -> case unsafeFreezeByteArray# mbar (generateLine mbar curLine 0# colCount genFunc s1) of 
     (# s2, bar #) -> initLines mat (curLine +# 1#) lineCount colCount genFunc 
         (writeByteArrayArray# mat curLine bar s2) -- only writes a pointer to the ByteArray 

generateMutable# :: Int# -> Int# -> (Int -> Int -> Int) -> State# s -> (# State# s, MutableArrayArray# s #) 
generateMutable# lineCount colCount genFunc s = 
    case newArrayArray# lineCount s of 
    (# s1, marrarr #) -> (# initLines marrarr 0# lineCount colCount genFunc s1 , marrarr #) 

crashBigMatrix :: Int 
crashBigMatrix = 
    case (runRW# $ \s -> case generateMutable# 150000# 4# (\x y -> x) s of 
    (# s1, marrarr #) -> (# s1, marrarr #)) of 
    (# _, m #) -> (MutableMatrix m) `seq` 2 

答えて

4

を試してみてください。

+0

実際。私は 'Int#'がハスケルで64ビットだったのを知らなかった、ありがとう! –

+2

これは使用しているGHCのビルドによって異なります。 – MathematicalOrchid

+0

もう少し拡張する:Haskellレポートは、 'Int'が少なくとも29ビットの精度を持つことを保証します。 GHCの32ビットビルドは 'Int#'を32ビットとして実装し、GHCの64ビットビルドはそれを64ビットとして実装します。 'GHC.Prim'のコメントを見てください。 – MathematicalOrchid