ここには、Repa とは関係のない基本的なモナドの質問と、いくつかの Repa 固有の質問があります。
Repa3 を使用してライブラリに取り組んでいます。効率的な並列コードの取得に問題があります。関数が遅延配列を返すようにすると、コードが非常に遅くなり、最大 8 コアまで拡張できます。このコードは、GHC プロファイラーごとに 20GB を超えるメモリを使用し、基本的な Haskell のボックス化されていないベクトルよりも数桁遅く実行されます。
あるいは、すべての関数がボックス化されていないマニフェスト配列を返すようにすると (たとえば、「マップ」を実行するときなど、関数内でまだ融合を使用しようとしている)、はるかに高速なコード (Haskell のボックス化されていないベクトルを使用するよりもまだ遅い) が得られます。まったく拡張できず、実際、コアが増えるとわずかに遅くなる傾向があります。
Repa-Algorithms の FFT サンプル コードに基づくと、正しいアプローチは常にマニフェスト配列を返すことです。遅延配列を返す必要がある場合はありますか?
FFT コードでは、'now' 関数も多用されています。ただし、コードで使用しようとすると、型エラーが発生します。
type Arr t r = Array t DIM1 r
data CycRingRepa m r = CRTBasis (Arr U r)
| PowBasis (Arr U r)
fromArray :: forall m r t. (BaseRing m r, Unbox r, Repr t r) => Arr t r -> CycRingRepa m r
fromArray =
let mval = reflectNum (Proxy::Proxy m)
in \x ->
let sh:.n = extent x
in assert (mval == 2*n) PowBasis $ now $ computeUnboxedP $ bitrev x
コードは「今」なしで正常にコンパイルされます。「今」では、次のエラーが発生します。
タイプ Array U (Z :. Int) と一致しませんでした
r' with
r' `r' は fromArray :: (BaseRing mr, Unbox r, Repr tr) => Arr tr -> CycRingRepa mr の型シグネチャによってバインドされた固定型変数ですC:\Users\crockeea\Documents\Code\LatticeLib\CycRingRepa.hs:50:1 で期待される型: CycRingRepa mr 実際の型: CycRingRepa m (配列 U DIM1 r)
これは私の問題ではないと思います。 モナドが「今」どのように機能するかを誰かが説明できれば助かります。私の最善の推定では、モナドは「Arr U (Arr U r)」を作成しているようです。「Arr U r」を期待していますが、これはデータ コンストラクターのパターンと一致します。何が起こっていて、どうすれば修正できますか?
型シグネチャは次のとおりです。
computeUnboxedP :: Fill r1 U sh e => Array r1 sh e -> Array U sh e
now :: (Shape sh, Repr r e, Monad m) => Array r sh e -> m (Array r sh e)
「今」を使用するのが適切な場合について、より良い考えを持っていると役に立ちます。
その他の Repa に関する質問: (FFT サンプル コードのように) computeUnboxedP を明示的に呼び出す必要がありますか、それともより一般的な computeP を使用する必要がありますか (アンボックス部分がデータ型によって推測されるため)。遅延配列またはマニフェスト配列をデータ型 CycRingRepa に格納する必要がありますか? 最終的には、このコードが Haskell Integers でも動作するようにしたいと考えています。これには、U 配列以外のものを使用する新しいコードを作成する必要がありますか? または、unbox 型の U 配列と Integers/boxed 型の他の配列を作成するポリモーフィック コードを作成できますか?
ここには多くの質問があることを認識しています。すべての回答に感謝します。