1votos

STM vs Bloqueos en Haskell

por josejuan hace 6 años

Efectivamente, el problema era lazy, no STM. Intenté muchos métodos (MVar, TVar, IORef, ...) pero nada ¡argh!. Tras consultar en http://stackoverflow.com/questions/12475363/speed-up-haskell-concurrency el rendimiento es fantástico, esperaré a usar la misma máquina para reportar una comparativa. XD XD XD XD

A raíz de la fructífera conversación surgida en el desafío de "La tela de araña", se propone comparar las estrategias STM vs Bloqueos más fondo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{-# LANGUAGE BangPatterns #-} 
import Control.Concurrent 
import Control.Monad 
import System.Environment(getArgs) 
import Data.Int 
import Control.Concurrent.STM 
 
addMany :: TVar Int64 -> [TVar Int64] -> Int64 -> Int64 -> IO () 
addMany !c !a !n !i = forM_ [1..i] (\_ -> forM_ a (shW n)) >> shW 1 c 
 
shR = atomically . readTVar 
shW !k !r = atomically $ 
  do x' <- readTVar r 
     writeTVar r $! (x' + k) -- <<<< ¡¡¡¡ éste es el culpable de todo !!!! 
 
main = do 
  (niters': nvars': nthreads': _) <- getArgs 
  let (niters, nvars, nthreads) = (read x, read y, read z) 
  c <- atomically $ newTVar 0 
  a <- mapM (\_ -> atomically $ newTVar 0) [1..nvars] 
  mapM_ (\k -> forkIO $ addMany c a k niters) [1..nthreads] 
  waitTo c nthreads 
  z <- mapM shR a 
  putStrLn $ show $ sum z 
 
-- ¿no hay forma de hacer un "join" entre procesos? 
waitTo !c !nth = do 
  threadDelay (100*1000) 
  w' <- shR c 
  if w' == nth 
    then return () 
    else waitTo c nth 
5 comentarios
0votos

Escrito por josejuan hace 6 años

Efectivamente, ahora la versión de Haskell usando STM es "sólo" 6.26 veces más lenta que la de bloqueos de C# debido, probablemente a usar STM (veremos con MVar).

$ time -f "%E, %M" mono ./counting.exe 1000 100000 6
Sum node values: 2100000000
0:03.20, 7864

$ time -f "%E, %M" ./counting 100000 1000 6 +RTS -N6
2100000000
0:20.03, 6564
0votos

Escrito por jneira hace 6 años

Vaya lujazo de respuesta en so por el pope del tag haskell (aunque la pregunta la merecia todo hay que decirlo)
Igual pruebo suerte yo con el de clojure :-P
0votos

Escrito por jneira hace 6 años

+1 al canto merecido
Ahora a estudiar el codigo...
0votos

Escrito por jneira hace 6 años

En el mismo equipo (intel core 2 duo) que las versiones de java clojure me da unos resultados curiosos:
int nitems=100;
int nthreads=10;
final int niters=1000;
Sum node values: 5500000
Time: 31 msecs

simple-example=> (-main "lock" "100" "10" "1000")
"Elapsed time: 60.030324 msecs"
Locking: 5500000
nil
simple-example=> (-main "atom" "100" "10" "1000")
"Elapsed time: 202.309477 msecs"
Atom: 5500000
nil
simple-example=> (-main "stm" "100" "10" "1000")
"Elapsed time: 1830.568508 msecs"
STM: 5500000
nil

Para las versiones de haskell (compiladas a codigo maquina, nada de vms creo):
*SimpleExampleSTM> :! timeit SimpleExampleMVar 1000 100 10
5500000
Version Number:   Windows NT 5.1 (Build 2600)
Elapsed Time:     0:00:00.171 (171 msecs)
Process Time:     0:00:00.046
System Calls:     2599
Context Switches: 803
Page Faults:      980
Bytes Read:       660522
Bytes Written:    176
Bytes Other:      5212

*SimpleExampleSTM> :! timeit SimpleExampleSTM 1000 100 10
5500000
Version Number:   Windows NT 5.1 (Build 2600)
Elapsed Time:     0:00:00.124 (124 msecs)
Process Time:     0:00:00.109
System Calls:     2419
Context Switches: 594
Page Faults:      964
Bytes Read:       5018
Bytes Written:    32
Bytes Other:      4276
*SimpleExampleSTM> :main 1000 100 10
Loading package array-0.4.0.0 ... linking ... done.
Loading package stm-2.3 ... linking ... done.
5500000


No se si he hecho las pruebas correctamente...
0votos

Escrito por jneira hace 6 años

He hecho las pruebas haciendo el timing interno para que sean mas parecidas a las mediciones de clojure y java:

>SimpleExampleMVar 100000 1000 6
Starting...
2100000000
Computation time: 11.781 sec
Done.

>SimpleExampleSTM 100000 1000 6
Starting...
2100000000
Computation time: 53.797 sec
Done.

>java -cp classes SimpleLocking
Sum node values: 2100000000
Time: 15.703 sec

java -cp classes;%CLOJURE_JAR% simple_example lock 1000 6 100000
"Elapsed time: 27.545 secs"
Locking: 2100000000

java -cp classes;%CLOJURE_JAR% simple_example lock-native 1000 6 100000
"Elapsed time: 80.913 secs"
Native locking: 2100000000

java -cp classes;%CLOJURE_JAR% simple_example atom 1000 6 100000
"Elapsed time: 95.143 secs"
Atom: 2100000000


Ya para empezar la version con mvars es mas rapida que la de java. A partir de ahi no hay color, sobre todo con la version STM (que ni siquiera he tenido paciencia para sacar).
Habra que investigar por que y si se pueden acercar ambas versiones

Comenta la solución

Tienes que identificarte para poder publicar tu comentario.