私の最初の本格的なプログラミング体験は、Haskell でした。その場しのぎのニーズのために、習得が容易で、コーディングが迅速で、保守が簡単なツールが必要でしたが、それはうまく機能したと言えます。
しかし、ある時点で、私のタスクの規模がはるかに大きくなり、C の方が適しているのではないかと考え、そのようになりました。たぶん、私はプログラミングのスキルが十分ではなかったのかもしれませんが、適切な Haskell は C と同じようなパフォーマンスができると聞いていたにもかかわらず、Haskell を C ほど高速にすることはできませんでした。
最近、Haskell をもう一度試してみようと思ったのですが、一般的な単純な (計算の観点から) タスクには依然として優れていますが、Collatz 予想などの問題で C の速度に匹敵することはできないようです。読みました:
Project Euler との速度比較: C vs Python vs Erlang vs Haskell
haskell を使用した collatz-list の実装
しかし、私が見たところ、次のような単純な最適化方法があります。
- Integer の代わりに Int64 のような「より厳密な」型を選択する
- GHC 最適化をオンにする
- 不要な計算や単純な関数を避けるなどの単純な最適化手法を使用する
Haskell コードを (方法論の点で) ほぼ同じ C コードに近づけないでください。[大規模な問題の場合] C に匹敵するパフォーマンスを実現しているように見える唯一のことは、最適化手法を使用して、コードを長く恐ろしいモナディック地獄にすることです。これは、Haskell (および私) が非常に重視している原則に反します。
Cバージョンは次のとおりです。
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int32_t col(int64_t n);
int main(int argc, char **argv)
{
int64_t n = atoi(argv[1]), i;
int32_t s, max;
for(i = 2, max = 0; i <= n; ++i)
{
s = col(i);
if(s > max) max = s;
}
printf("%d\n", max);
return 0;
}
int32_t col(int64_t n)
{
int32_t s;
for(s = 0; ; ++s)
{
if(n == 1) break;
n = n % 2 ? 3 * n + 1 : n / 2;
}
return s;
}
そして Haskell バージョン:
module Main where
import System.Environment (getArgs)
import Data.Int (Int32, Int64)
main :: IO ()
main = do
arg <- getArgs
print $ maxCol 0 (read (head arg) :: Int64)
col :: Int64 -> Int32
col x = col' x 0
col' :: Int64 -> Int32 -> Int32
col' 1 n = n
col' x n
| rem x 2 == 0 = col' (quot x 2) (n + 1)
| otherwise = col' (3 * x + 1) (n + 1)
maxCol :: Int32 -> Int64 -> Int32
maxCol maxS 2 = maxS
maxCol maxS n
| s > maxS = maxCol s (n - 1)
| otherwise = maxCol maxS (n - 1)
where s = col n
TL;DR: Haskell コードは、計算上単純なタスクの場合にのみ、すばやく作成でき、保守も簡単で、パフォーマンスが重要な場合にこの特性を失いますか?