2

並行して計算を行い、結果をSTArrayに書き込もうとしています。このコードは、私がやろうとしていることを示していると思います。ただし、コンパイルエラーが発生します。

import Control.Monad
import Control.Monad.ST
import Control.Parallel
import Data.Array.ST

main = do
    arr <- newArray ((0,0), (5,5)) 0 :: ST s (STArray s (Int, Int) Int)
    runSTArray $ do
        par (writeArray arr (1,1) 17) (writeArray arr (2,2) 23)
        return arr
    print arr

これはどのようにすればよいですか?

4

2 に答える 2

10

newArrayタイプが。のを使用しますST s (STArray s (Int, Int) Int)。ただし、main関数の本体で使用します。つまり、すべてdoの型が必要IOです。STではないIOため、タイプを一致させることはできません。

まず、モナドnewArrayにアクセスできるコンテキストに移動する必要があります。STこのコンテキストはもちろんの本文で利用できるrunSTArrayので、本文を次のように変更します。

    runSTArray $ do
        arr <- newArray ((0,0), (5,5)) 0 :: ST s (STArray s (Int, Int) Int)
        par (writeArray arr (1,1) 17) (writeArray arr (2,2) 23)
        return arr

次に、動作を再考する必要がありますparpar並列の純粋な計算を作成するためのものであり、モナディックアクションには使用できません。モナドは一般的に並列化することはできません。特に、STモナドは並列計算の代替手段さえ提供していません。配列への並列書き込みは競合状態につながる可能性があるため(同じセルを上書きするとどうなりますか?どの書き込みがカウントされ、どの書き込みがカウントされませんか?)、ここで並列処理を許可することは安全ではありません。配列を順番に変更する必要があります。

    runSTArray $ do
        arr <- newArray ((0,0), (5,5)) 0 :: ST s (STArray s (Int, Int) Int)
        writeArray arr (1,1) 17
        writeArray arr (2,2) 23
        return arr

ただし、書き込みは高価ではありません。費用がかかる可能性があるのは値の計算です。計算1723てその場で実行したいとします。その後、次のことを行うことができます。

let a = someLongCalculation 12534
    b = a `par` (someLongCalculation 24889)
writeArray arr (1, 1) a
writeArray arr (2, 2) b

最後に、それrunSTArrayが結果の配列を返すことを理解する必要があるため、次のように格納する必要があります。

import Control.Monad
import Control.Monad.ST
import Control.Parallel
import Data.Array.ST

main =
  let pureArr =
        runSTArray $ do
          arr <- newArray ((0,0), (5,5)) 0 :: ST s (STArray s (Int, Int) Int)
          writeArray arr (1,1) 17
          writeArray arr (2,2) 23
          return arr
  in print pureArr

STArrayここでは、sが正しい解決策ではないと思います。repa並列対称配列計算が必要な状況のように、より強力な配列ライブラリを使用する必要があります。

于 2012-04-09T21:38:56.910 に答える
1

par純粋な操作を並行して作成するためのものです。あなたは効果的な操作を構成しています。パーは使えません。さらに、並列処理効果であり(少なくとも突然変異で構成されている場合)、STモナドでは使用できません。コードを構造化する正しい方法についてアドバイスすることはできません。なぜなら、実際の問題のドメインが何であるかを確認するには物事があまりにも削減されているからです。ただし、私の一般的なアドバイスは、fork(IOモナド内)のような明示的な同時実行構造を使用する、変異型配列ではなく純粋な操作を使用することです。

于 2012-04-09T21:38:18.597 に答える