19102010 sake
久しぶりに臥龍梅のんだけど、すっきりしていてよかった。

臥龍梅は純米(吟醸)よりは吟醸のほうが好きかも
18102010 life
いわゆる参照カウントというやつですな。
お見合いパーティーの文脈でマーク・アンド・スイープを考えてみると
参考
要するに次世代というか今風のGCは自分で断らなくてもマークしとくと親のほうが良きにはからってくれるみたいな感じ?
んー小町の見過ぎだな。過干渉GCとかなんかメリットを見いだせるかもしれんよ。介護GCとかforkされたプロセスが親プロセスの面倒をみるとか。
情報処理の試験を受けに静岡に行ったので帰りに伊勢丹の裏手にあるあかつき屋に行ってきた。

あっさりを注文。煮干が効いてて美味い。好みの味だった。

来週も静岡に行く。Haskell読書会もあと三回。次回は切符遊びの章だな。
17102010 work
創薬研究というのは細かな作業が沢山あり、変化の激しいテスト工程なのに、そのインフラにはBTSとかITSとかないのが不自然だと思っていて、この前寄稿したときにちと触れといた。僕はソフトウェア業界にいるわけじゃないけど、問題解決の方法論としては似たような部分があるから参考になるんじゃないかと常々思っていたら、ズバリな本が出ることを知ってすぐに予約しといた。
で、一昨日届いたので今日の移動時に一気に読んだ。
チケット駆動開発的なアプローチは自分の仕事管理では既に取り入れていたのであった。自分では文書駆動開発だと思っていたけど本書を読んだら、これは明らかにチケット駆動開発のコンテクストだよなと。
個人的には第一部の技法は非常に勉強になった。第二部は実際にRedmineをどう使うかという話はソフトウェア開発としては色々面白かったが、自分ではRedmine使ったことがないので、ピンと来ない話も幾つかあった。実際に使って見ながら本書を読み直せば新たな発見があるのだろうと思うので、今度、創薬のプロジェクトで、Redmine使えないか検討してみようっと。そうすれば創薬向けのITSとかBTSみたいなものがみえてくるような気がするんだよな。アジャイル創薬とかそういう方法論は一部試され始めているのでその先はこういうツールの重要性が認識されるだろうと思うんだよね。
それにしても、「ツールでサポートすれば行動が変わる。行動が変われば考え方が変わる」というのはいい言葉ですな。うちのインフラやってるチームにも本書を薦めてみようっと。
以下、メモ。
MapReduce、ただし、サンプルの通りでは動かない。
Real World Haskell―実戦で学ぶ関数型言語プログラミングControl.Parallel.Strategiesを読むと
とのことなのでそう書きなおしてみた。
$ time ./LineCount +RTS -N1 -RTS test.log
test.log: 2146144
real 0m1.273s
user 0m0.709s
sys 0m0.318s
$ time ./LineCount +RTS -N2 -RTS test.log
test.log: 2146144
real 0m0.652s
user 0m0.781s
sys 0m0.373s
お、速くなった。
module MapReduce
(
mapReduce
, simpleMapReduce
-- exported for convenience
-- , rnf
-- , rwhnf
) where
import Control.Parallel (pseq)
import Control.Parallel.Strategies
simpleMapReduce
:: (a -> b)
-> ([b] -> c)
-> [a]
-> c
simpleMapReduce mapFunc reduceFunc = reduceFunc . map mapFunc
mapReduce
:: Strategy b
-> (a -> b)
-> Strategy c
-> ([b] -> c)
-> [a]
-> c
mapReduce mapStrat mapFunc reduceStrat reduceFunc input =
mapResult `pseq` reduceResult
where mapResult = parMap mapStrat mapFunc input
reduceResult = reduceFunc mapResult `using` reduceStrat
module LineChunks
(
chunkedReadWith
) where
import Control.OldException (bracket, finally)
import Control.Monad (forM, liftM)
--import Control.Parallel.Strategies
import Control.DeepSeq (NFData, rnf)
import Data.Int
import qualified Data.ByteString.Lazy.Char8 as LB
import GHC.Conc (numCapabilities)
import System.IO
data ChunkSpec = CS {
chunkOffset :: !Int64
,chunkLength :: !Int64
} deriving (Eq, Show)
withChunks :: (NFData a) =>
(FilePath -> IO [ChunkSpec])
-> ([LB.ByteString] -> a)
-> FilePath
-> IO a
withChunks chunkFunc process path = do
(chunks, handles) <- chunkedRead chunkFunc path
let r = process chunks
(rnf r `seq` return r) `finally` mapM_ hClose handles
chunkedReadWith :: (NFData a) =>
([LB.ByteString] -> a) -> FilePath -> IO a
chunkedReadWith func path =
withChunks (lineChunks (numCapabilities * 4)) func path
chunkedRead :: (FilePath -> IO [ChunkSpec])
-> FilePath
-> IO ([LB.ByteString], [Handle])
chunkedRead chunkFunc path = do
chunks <- chunkFunc path
liftM unzip . forM chunks $ \spec -> do
h <- openFile path ReadMode
hSeek h AbsoluteSeek (fromIntegral (chunkOffset spec))
chunk <- LB.take (chunkLength spec) `liftM` LB.hGetContents h
return (chunk, h)
lineChunks :: Int -> FilePath -> IO [ChunkSpec]
lineChunks numChunks path = do
bracket (openFile path ReadMode) hClose $ \h -> do
totalSize <- fromIntegral `liftM` hFileSize h
let chunkSize = totalSize `div` fromIntegral numChunks
findChunks offset = do
let newOffset = offset + chunkSize
hSeek h AbsoluteSeek (fromIntegral newOffset)
let findNewline off = do
eof <- hIsEOF h
if eof
then return [CS offset (totalSize - offset)]
else do
bytes <- LB.hGet h 4096
case LB.elemIndex '\n' bytes of
Just n -> do
chunks@(c:_) <- findChunks (off + n + 1)
let coff = chunkOffset c
return (CS offset (coff - offset):chunks)
Nothing -> findNewline (off + LB.length bytes)
findNewline newOffset
findChunks 0
module Main where
import Control.Monad (forM_)
import Data.Int (Int64)
import qualified Data.ByteString.Lazy.Char8 as LB
import System.Environment (getArgs)
import LineChunks (chunkedReadWith)
import MapReduce (mapReduce)
import Control.Parallel.Strategies
lineCount :: [LB.ByteString] -> Int64
lineCount = mapReduce rdeepseq (LB.count '\n')
rdeepseq sum
main :: IO ()
main = do
args <- getArgs
forM_ args $ \path -> do
numLines <- chunkedReadWith lineCount path
putStrLn $ path ++ ": " ++ show numLines
16102010 家庭菜園
そら豆が、カラスかなんかにほじられて全滅しているっぽい。やっぱポットで発芽させて植えたほうが無難か。まだ間に合うかな、間に合うようだったら明日種買ってきて、ダメだったら潔く苗を買おう。
一方、ラディッシュ、春菊、ほうれん草は無事に発芽。
ラディッシュ、間引かないと。

春菊とほうれん草。

それにしても石ころ多いなぁ。土ふるいでも作って石取りしようかなぁ。
クィックソートを並列で。
正規形(NF),頭部正規形(HNF),弱頭部正規形(WHNF)を理解した。
Real World Haskell―実戦で学ぶ関数型言語プログラミングmodule Sorting where
import Control.Parallel (par, pseq)
parSort :: (Ord a) => [a] -> [a]
parSort (x:xs) = force greater `par` (force lesser `pseq`
(lesser ++x:greater))
where lesser = parSort [y|y <- xs, y<x]
greater = parSort [y|y <- xs, y>=x]
parSort _ = []
force :: [a] -> ()
force xs = go xs `pseq` ()
where go (_:xs) = go xs
go [] = 1
sort :: (Ord a) => [a] -> [a]
sort (x:xs) = lesser ++ x:greater
where lesser = sort [y|y <- xs, y<x]
greater = sort [y|y <- xs, y>=x]
sort _ = []
parSort2 :: (Ord a) => Int -> [a] -> [a]
parSort2 d list@(x:xs)
| d <= 0 = sort list
| otherwise = force greater `par` (force lesser `pseq`
(lesser ++x:greater))
where lesser = parSort2 d' [y|y <- xs, y<x]
greater = parSort2 d' [y|y <- xs, y>=x]
d' = d - 1
parSort2 _ _ = []
で実際に時間を測ってみると
-- parSort2
kzfm:ch24 kzfm$ ./SortMain +RTS -N2 -RTS 1000000
we have 1000000 elements to sort.
sorted all 1000000 elements.
11.419152s elapsed.
-- sort
kzfm:ch24 kzfm$ ./SortMain 1000000
we have 1000000 elements to sort.
sorted all 1000000 elements.
6.212093s elapsed.
-- parSort -N2
kzfm:ch24 kzfm$ ./SortMain +RTS -N1 -RTS 1000000
we have 1000000 elements to sort.
sorted all 1000000 elements.
6.188667s elapsed.
-- parSort -N2
kzfm:ch24 kzfm$ ./SortMain +RTS -N2 -RTS 1000000
we have 1000000 elements to sort.
sorted all 1000000 elements.
35.960397s elapsed.
GCのせいかな、よくわからん。
並行マルチコアプログラミング
Real World Haskell―実戦で学ぶ関数型言語プログラミングimport Control.Concurrent
communicate = do
m <- newEmptyMVar
forkIO $ do
v <- takeMVar m
putStrLn ("received" ++ show v)
putStrLn "sending"
putMVar m "wake up!"