Есть две реализации на хаскель:

{-# LANGUAGE LambdaCase #-}

module Main (main) where

import System.Clock (Clock(ProcessCPUTime), getTime, toNanoSecs)
import System.Environment (getArgs)
import System.Exit (exitFailure)
import Text.Printf (printf)

type Matrix = `Double`

main :: IO ()
main = do
n <- getArgs >>= \case
[a] -> pure (read a)
_ -> exitFailure

let a = newMatrix n
b = newMatrix n
c = newMatrix n

t1 <- clock
let c' = matrixMult n a b c
t2 <- clock

printf "%dns\n" (t2 - t1)
printf "% 8.6f\n" (c' !! (n `div` 2) !! (n `div` 2))

newMatrix :: Int -> Matrix
newMatrix n =
let tmp = 1 / fromIntegral n / fromIntegral n in
[ [ tmp * (i - j) * (i + j)
| j <- [0 .. fromIntegral (pred n)]
]
| i <- [0 .. fromIntegral (pred n)]
]

matrixMult :: Int -> Matrix -> Matrix -> Matrix -> Matrix
matrixMult n a b _ =
let t = [ [ b!!j!!i
| j <- [0 .. pred n]
]
| i <- [0 .. pred n]
]
c = [ [ sum [ a!!i!!k * t!!j!!k | k <- [0 .. pred n] ]
| j <- [0 .. pred n]
]
| i <- [0 .. pred n]
]
in c

matrixPrint :: Int -> Matrix -> String
matrixPrint _ = unlines . fmap (unwords . fmap (printf "% 8.6f")

clock :: IO Integer
clock = toNanoSecs <$> getTime ProcessCPUTime
{-# LANGUAGE LambdaCase #-}

module Main (main) where

import System.Clock (Clock(ProcessCPUTime), getTime, toNanoSecs)
import System.Environment (getArgs)
import System.Exit (exitFailure)
import Text.Printf (printf)
import Data.Array.Unboxed
import Data.Array.IO
import Data.Array.Base
import GHC.Arr (unsafeIndex)

-- Matrix multiplication benchmark

type Matrix = UArray (Int, Int) Double

main :: IO ()
main = do
[n] <- getArgs >>= \case
[a] -> pure ([read a :: Int])
_ -> exitFailure

t1 <- clock
let a = newMatrix n
b = newMatrix n

let c' = matrixMult a $ transpose b

printf "% 8.6f\n" (c' ! ((n `div` 2), (n `div` 2)) )

t2 <- clock
printf "%ds\n" $ (t2 - t1) `div` 1000000000

newMatrix :: Int -> Matrix
newMatrix n =
let tmp = 1 / fromIntegral n / fromIntegral n :: Double in
array ((0, 0), (pred n, pred n))
[((i,j), tmp * fromIntegral(i - j) * fromIntegral (i + j))
| i <- range (0, pred n),
j <- range (0, pred n) ]


transpose :: Matrix -> Matrix
transpose x = array resultBounds [((j,i), x!(i,j))
| i <- range (li,ui),
j <- range (lj,uj) ]
where ((li,lj),(ui,uj)) = bounds x
resultBounds = ((lj,li),(uj,ui))

matrixMult :: Matrix -> Matrix -> Matrix
matrixMult x y = array resultBounds [((i,j),
let basei = rowIndex x i
basej = rowIndex y j
in sum [unsafeAt x ( basei + k ) * unsafeAt y ( basej + k )
| k <- range (lj,uj) ]
)
| i <- range (li,ui),
j <- range (li',ui') ]

where ((li,lj),(ui,uj)) = bounds x
((li',lj'),(ui',uj')) = bounds y
resultBounds | (lj,uj)==(lj',uj') = ((li,li'),(ui,ui'))
| otherwise = error "matMult: incompatible bounds"
rowIndex arr n = index (bounds arr) (n,0)

clock :: IO Integer
clock = toNanoSecs <$> getTime ProcessCPUTime

Есть код на C++:

#include <range/v3/view.hpp>
#include <range/v3/numeric/inner_product.hpp>
#include <chrono>

using namespace ranges::view;

int main(int argc, char * argv[]) {
size_t N = 3000;
if(argc > 1) N = std::atol(argv[1]);

auto matrix = [](size_t n) {
return iota(0ul, n * n) | transform([n, tmp = 1. / n / n](auto x) {
ssize_t i = x / n, j = x % n;
return tmp * (i - j) * (i + j);
});
};

auto a = matrix(N), b = matrix(N);

auto column = [N](const auto & m, size_t n) {
return slice(m, n, m.size()) | stride(N);
};

auto row = [N](const auto & m, size_t n) {
return slice(m, n * N, n * N + N);
};

auto mul = [=](const auto & a, const auto & b) {
return iota(0ul, N) | transform([=](auto i) {
return iota(0ul, N) | transform([=](auto j) {
return ranges::inner_product(row(a, i), column(b, j), 0.);
});
});
};


auto start = std::chrono::high_resolution_clock::now();
auto c = mul(a, b);
auto time = std::chrono::high_resolution_clock::now() - start;

fprintf(stderr, "%luns\n", size_t(std::chrono::duration_cast<std::chrono::nanoseconds>(time).count()));
fprintf(stderr, "%f\n", c[N/2][N/2]);
}

Собирать код так:

$ git clone github.com/ericniebler/range-v3.git
$ g++ main.cpp -std=gnu++2a -march=native -Ofast -fwhole-program -funroll-all-loops -fconcepts -Irange-v3/include -o cpp
//либо
$ clang++ main.cpp -std=gnu++2a -march=native -Ofast -Irange-v3/include -o cpp

$ ghc main.hs -o hs

Запускать так:

$ time ./cpp 123

61ns
-11.620506

real 0m0,001s
user 0m0,000s
sys 0m0,001s

$ time ./hs 123
-11.620506
0s

real 0m0,152s
user 0m0,146s
sys 0m0,005s


Нужно запустить и написать сюда результаты. Так же, желательно дать оценки коду(по мотивам троек).








 , , ,






URL записи