雑記帳

ちょっとした文章とかメモ書きとか。

カテゴリーアーカイブ: Mac

fluent-bit 0.2.0 available in Homebrew now

Today, fluent-bit, which is a Data Collector for IoT, formula has been merged into Homebrew master.

You can install fluent-bit like this:

$ brew install fluent-bit

For now, fluent-bit 0.2.0 will be installed in your OS X.

Or, try to install development version:

$ brew install fluent-bit --HEAD

In more detail about fluent-bit, please refer to the official fluent-bit document: http://fluentbit.io/documentation/

Happy logging!

広告

MikutterInstallBattle with nokogiri 1.6.5 at develop branch

#mikutterinstallbattle with nokogiri 1.6.5

Homebrewでlibxml2を入れている場合は、OS Xのライブラリと競合しないようにkeg-onlyフラグが付けられている。

これは、Cellarには入れるが、system wideに参照する事ができない状態にしてインストールするという意味。

それを参照するには以下の記述をbashrcなどに加えれば良い。

export PKG_CONFIG_PATH=/usr/local/opt/libffi/lib/pkgconfig:/usr/local/opt/libxml2/lib/pkgconfig:$PKG_CONFIG_PATH

libffiは要らないかも知れない。

おしまい。

HaskellでOpenCLを使ってみる その2

 Control.Parallel.OpenCLを使う

今回はその2。

Control.Parallel.OpenCLには通常のOpenCLと同じく
OpenCLのカーネル関数をビルドすることや、
ホストコードの実行などをHaskellから呼び出せるようになっています。

Control.Parallel.OpenCLのGithub:https://github.com/zhensydow/opencl にexampleがあるのでそれを見ていけば基本的には問題はないです。

しかしこのライブラリ、単にラップしているだけなので便利なユーティリティ関数は用意されていません。

という事で、少し手を加えた実行例を示します。

Haskellでは型情報が大いに情報を持っているのでそれを参考にしながら書いていきます。

OpenCLではカーネル関数を読み込んでデバイスドライバ側でビルドを走らせます。
そのカーネル関数を読み込む関数を見てみましょう。

clCreateProgramWithSource関数ですね。

clCreateProgramWithSource :: CLContext-> String -> IO CLProgram

見たところ第二引数にStringが渡されているので、
これを外部ファイルから読み込む関数を使って渡してやればOpenCLの本領(?)が発揮できるでしょう。

ファイル読み込み

ファイル読み込みはエラーも伴うのでとりあえずcatchでベタ書きしてみます。

onError関数でエラーハンドリングをしています。

import Prelude hiding ( catch )
import System.IO 
import System.Exit
import Control.Exception
--error handling
onError :: String -> IOError -> IO String
onError filename error = do
  hPutStrLn stderr $ "File not found: " ++ filename
  exitWith(ExitFailure 1)

--read from file
programSourceFromFile :: IO String
programSourceFromFile = do let clprogramName = "testdouble.cl"
                           catch (readFile clprogramName)
                                 (onError clprogramName)

と書いてみました。はい、これでIOの作用をもつStringを返す関数が書けました。

ホスト側のコード

これを用いて書いたOpenCLのHaskellによるホストコードは以下:
–testcl.hs–

import Prelude hiding ( catch )
import Control.Parallel.OpenCL
import Foreign( castPtr, nullPtr, sizeOf )
import Foreign.C.Types( CFloat,CDouble )
import Foreign.Marshal.Array( newArray, peekArray )
import System.IO
import System.Exit
import Control.Exception

--error handling
onError :: String -> IOError -> IO String
onError filename error = do
  hPutStrLn stderr $ "File not found: " ++ filename
  exitWith(ExitFailure 1)

--read from file
programSourceFromFile :: IO String
programSourceFromFile = do let clprogramName = "testdouble.cl"
                           catch (readFile clprogramName)
                                 (onError clprogramName)

main :: IO ()
main = do
  -- Initialize OpenCL
  (platform:_) <- clGetPlatformIDs
  (dev:_) <- clGetDeviceIDs platform CL_DEVICE_TYPE_GPU
  context <- clCreateContext [] [dev] print
  q <- clCreateCommandQueue context dev []

  -- Compile and get binaries
  clsource <- programSourceFromFile
  program <- clCreateProgramWithSource context clsource
  clBuildProgram program [dev] ""
  bins <- clGetProgramBinaries program

  -- Create kernel from binaries
  (program2,_) <- clCreateProgramWithBinary context [dev] bins
  let clkernelBuildOption = ""
      clkernelName = "arraydev"
  clBuildProgram program2 [dev] clkernelBuildOption
  kernel <- clCreateKernel program2 clkernelName
  -- Initialize parameters
  let original = [0 .. 20] :: [CDouble] -- or [CFloat]
      elemSize = sizeOf (0 :: CDouble) -- or CFloat
      vecSize = elemSize * length original
  putStrLn $ "Original array = " ++ show original
  input <- newArray original

  mem_in <- clCreateBuffer context [CL_MEM_READ_ONLY, CL_MEM_COPY_HOST_PTR] (vecSize, castPtr input)
  mem_out <- clCreateBuffer context [CL_MEM_WRITE_ONLY] (vecSize, nullPtr)

  clSetKernelArgSto kernel 0 mem_in
  clSetKernelArgSto kernel 1 mem_out

  -- Execute Kernel
  eventExec <- clEnqueueNDRangeKernel q kernel [length original] [1] []

  -- Get Result
  eventRead <- clEnqueueReadBuffer q mem_out True 0 vecSize (castPtr input) [eventExec]
  result <- peekArray (length original) input
  putStrLn $ "Result array   = " ++ show result
  let resultcpu = map (*2)[0.0,1.0 .. 20.0]
  putStrLn $ unlines ["compare"
                     ,"cpu : " ++ show resultcpu
                     ,"gpu : " ++ show result
                     ,"same? : " ++ show (resultcpu == result)]

  return ()

ホストコードはこのようになりました。

以下の部分でOpenCLのカーネル関数のソースを読み込んでいます。

-- Compile and get binaries
clsource <- programSourceFromFile
program <- clCreateProgramWithSource context clsource

この関数により、OpenCLのソースを書き換えただけではホスト側のコンパイルは不要になりました。

ここで、HaskellからFFIを用いてCの関数を呼び出しているので、Foreignモジュールをインポートしています。–Get Result から後は得られた値を表示したり、比較したりしています。

[CDouble]のListを2倍にした値を求めるのにOpenCLのカーネル関数に値を渡したり、値を戻してきたりするのにかなりステップが要るのがめんどくさい。

CPU側でその値を得るには

let resultcpu = map (*2)[0.0,1.0 .. 20.0]

だけで良かった。かんたん!

Control.Parallel.OpenCLのGithubの例では文字列にして渡していますが、このようにしたほうがOpenCL側のコードを書きやすくなります。

OpenCLのカーネル関数側のコード

次にOpenCL側のカーネル関数のコードです。

–testdouble.cl–

#ifdef cl_khr_fp64
  #pragma OPENCL EXTENSION cl_khr_fp64 : enable
#elif defined(cl_amd_fp64)
  #pragma OPENCL EXTENSION cl_amd_fp64 : enable
#else
  #error Double precision floating point not supported by OpenCL implementation.
#endif
__kernel void arraydev(__global const double *in, __global double *out ){
  int id = get_global_id(0);
  out[id] = 2.0*in[id];
}

何やら悲しみに満ち溢れたpragmaがありますね。これはOpenCL1.1のデフォルトのプロファイルではdouble型の変数がカーネル関数で許可されていないのでそれを有効にするpragmaです。
これをさっきのtestcl.hsと同じフォルダに入れておきます。

もしもエラーになってしまうなら使っているOpenCLデバイスがdouble型に対応してないので

  • CDouble ->CFloat
  • double -> float

の書き換えと#error行の消去を行なってみてください。

実行

コンパイルするには
Linux:

$ ghc --make tecstcl.hs

OSX:

$ ghc -framework OpenCL -o testcl testcl.hs

とします。

これを実行すると以下の結果が得られます。

./testcl
Original array = [0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0]
Result array   = [0.0,2.0,4.0,6.0,8.0,10.0,12.0,14.0,16.0,18.0,20.0,22.0,24.0,26.0,28.0,30.0,32.0,34.0,36.0,38.0,40.0]
compare
cpu : [0.0,2.0,4.0,6.0,8.0,10.0,12.0,14.0,16.0,18.0,20.0,22.0,24.0,26.0,28.0,30.0,32.0,34.0,36.0,38.0,40.0]
gpu : [0.0,2.0,4.0,6.0,8.0,10.0,12.0,14.0,16.0,18.0,20.0,22.0,24.0,26.0,28.0,30.0,32.0,34.0,36.0,38.0,40.0]
same? : True

OpenCLデバイス側で実行した値は渡す前に比べて2倍になっていますね。

HaskellからOpenCLを使ってみた一例でした。

HaskellでOpenCLを使ってみる

HaskellでOpenCLを使ってみると言う記事。

HackageにControl.Parallel.OpenCLと言うライブラリがあったのでこれを使ってきます。

Control.Parallel.OpenCLの導入

cabalで導入すれば終わりなのですが少し依存関係があるので注意。
このパッケージはc2hsをcabal install時に要求する為、それをまずインストールします。

% cabal install c2hs

これでc2hsを入れた後、c2hsは
Linux:
$HOME/.cabal/bin
OSX:
$HOME/Library/Haskell/bin
へインストールされます。これを$PATHへ追加します。

例えば以下のようなコマンドで一時的に追加します。
bash/zsh:
export PATH=$HOME/.cabal/bin:$PATH
csh/tcsh:
set path=($HOME/.cabal/bin $path)
bashrcやzshrcに書いておいてもいいかも知れません。

これで

% cabal install opencl

として Control.Parallel.OpenCLが入ります。

使ってみる

早速使ってみます。
–testCL.hs–

import Control.Parallel.OpenCL

-- clDeviceCheck
clDeviceCheck :: IO ()
clDeviceCheck = do
  (platform:_) <- clGetPlatformIDs
  (dev:_<- clGetDeviceIDs platform CL_DEVICE_TYPE_ALL
  cl_e <- clGetDeviceExtensions dev
  cl_t <- clGetDeviceType dev
  cl_ven <- clGetDeviceVendor dev
  cl_venid <- clGetDeviceVendorID dev
  cl_driver <- clGetDeviceDriverVersion dev
  cl_name <- clGetDeviceName dev
  cl_v <- clGetDeviceVersion platform
  cl_p <- clGetDeviceProfile platform
  cl_maxunit <- clGetDeviceMaxComputeUnits dev
  cl_freq <- clGetDeviceMaxClockFrequency dev
  cl_gmem_t <- clGetDeviceGlobalMemCacheType dev
  cl_gmem_s <- clGetDeviceGlobalMemSize dev
  cl_mem_cache <- clGetDeviceGlobalMemCachelineSize dev
  cl_dim <- clGetDeviceMaxWorkItemDimensions dev
  cl_work <- clGetDeviceMaxWorkGroupSize dev
  cl_item <- clGetDeviceMaxWorkItemSizes dev
  cl_res <- clGetDeviceProfilingTimerResolution dev
  cl_maxmem <- clGetDeviceMaxMemAllocSize dev
  cl_const_buffer <- clGetDeviceMaxConstantBufferSize dev
  cl_img <- clGetDeviceImageSupport dev
  cl_double <- clGetDeviceDoubleFPConfig dev
  cl_single <- clGetDeviceSingleFPConfig dev
  cl_capable <- clGetDeviceExecutionCapabilities dev

  putStrLn $ unlines $
              [ "Device Id: " ++ show dev
               , "Device Info: " ++ cl_e
               , "Device Type: "  ++ show cl_t
               , "Device Vendor: "  ++ cl_ven
               , "Vendor ID: "  ++ show cl_venid
               , "Device Driver Version: "  ++ cl_driver
               , "Device Name: "  ++ cl_name
               , "Device Version: "  ++ cl_v
               , "Device Profile: "  ++ cl_p
               , "Max unit: "  ++ show cl_maxunit
               , "Max clock frequency: "  ++ show cl_freq
               , "Global Memory Cache Type : "  ++ show cl_gmem_t
               , "Global Memory Size: "  ++ show cl_gmem_s
               , "Global Memory Cacheline Size: "  ++ show cl_mem_cache
               , "Max dimension: "  ++ show cl_dim
               , "Max work group size: "  ++ show cl_work
               , "Max Work Item: "  ++ show cl_item
               , "CL timer resolution: "  ++ show cl_res
               , "Max alloc Memory size: "  ++ show cl_maxmem
               , "Max constant buffer size: "  ++ show cl_const_buffer
               , "Device image Support: "  ++ show cl_img
               , "Double precision floating point: "  ++ show cl_double
               , "Single precision floating point: " ++ show cl_single
               , "Device capability: " ++ show cl_capable]

main :: IO ()
main = clDeviceCheck

となりました。これではまだ一つのデバイスしか対応できてないです。

複数デバイスに対応したものはshelarcyさんが書いてくださいました。
複数デバイス対応版はこちら→http://ideone.com/2vQjl

これをghcでコンパイルするには
Linux:

% ghc --make testCL.hs

OSX:

% ghc -framework OpenCL -o testCL testCL.hs

とします。

動かしてみる

  • Ubuntu64bit
  • GTX550Ti NVIDIA
  • Driver304.37

の時の結果は以下のようになりました。

% ./testCL
Device Id: 0x0000000001e39c50
Device Info: cl_khr_byte_addressable_store cl_khr_icd cl_khr_gl_sharing cl_nv_compiler_options cl_nv_device_attribute_query cl_nv_pragma_unroll  cl_khr_global_int32_base_atomics cl_khr_global_int32_extended_atomics cl_khr_local_int32_base_atomics cl_khr_local_int32_extended_atomics cl_khr_fp64
Device Type: [CL_DEVICE_TYPE_GPU]
Device Vendor: NVIDIA Corporation
Vendor ID: 4318
Device Driver Version: 304.37
Device Name: GeForce GTX 550 Ti
Device Version: OpenCL 1.1 CUDA
Device Profile: FULL_PROFILE
Max unit: 4
Max clock frequency: 1800
Global Memory Cache Type : CL_READ_WRITE_CACHE
Global Memory Size: 1073610752
Global Memory Cacheline Size: 128
Max dimension: 3
Max work group size: 1024
Max Work Item: [1024,1024,64]
CL timer resolution: 1000
Max alloc Memory size: 268402688
Max constant buffer size: 65536
Device image Support: True
Double precision floating point: [CL_FP_DENORM,CL_FP_INF_NAN,CL_FP_ROUND_TO_NEAREST,CL_FP_ROUND_TO_ZERO,CL_FP_ROUND_TO_INF,CL_FP_FMA]
Single precision floating point: [CL_FP_DENORM,CL_FP_INF_NAN,CL_FP_ROUND_TO_NEAREST,CL_FP_ROUND_TO_ZERO,CL_FP_ROUND_TO_INF,CL_FP_FMA]
Device capability: [CL_EXEC_KERNEL]

OpenCL 1.1のFull Profileに対応しているようです。
GTX550TiのカードはOpenCLでも倍精度浮動小数点型が使えるみたいですね。

Ubuntu12.04でcabalがLexical Error ‘#’になる場合

Ubuntu12.04のcabalはLexical Error ‘#’でエラーになります。
これはコンフィグのミスに依るもので、LANG=C環境なら正常に動きます。

この場合は

% cabal install ...

では無く

% LANG=C cabal install ...

としてみてください。

参考:https://github.com/aleator/CV/wiki/BuildProblems のLexical Error ‘#’項

Mac kernel extenstionとはなんぞや

kernel extentionとはなんぞ

Mac OSXのカーネルにはLinuxカーネルやNTカーネルと同じく
カーネルエクステンションの機構があります。

そしてOSXではXcodeの強力な手助けがあります。

既にkernel extensionのひな形がXcodeに登録されているので
これを使わない手段はないですね。

作ってみる

登録されているひな形です:

今回はI/O Driverとして作成を試みてみましょう。

Javaっぽいような命名規則でcompany nameをつけます。
com.driver.helloworld
くらいにしておきます。

info.plistを編集して
InfoDiecttory version6.0(OSX 10.5+)
をしておきます。

Xcode4.0+ではデフォルトのコンパイラがLLVM clangになっていますが、
これだとカーネルエクステンションがどうも作れないようで
LLVM clang -> LLVM gcc 4.2
へ。

動かしているMacのカーネルのアーキテクチャには注意です。

  • powerpc  or i386 (<=10.5)
  • i386 or x86_64 10.6
  • x86_64 10.7

になっています。雪豹なMacを使っている人は注意してください。
カーネルのアーキテクチャが違っていてロードできなくてかなりハマりました…orz

以下プロジェクトの設定のスクリーンショットです。

こんな感じなxcode projectが作れればkextが作成できます。

ロードしてみる

作成したカーネルエクステンションは

$sudo chwon -R root:wheel <作成したエクステンションの名前>.kext

で所有者を変更して

$sudo kextload <作成したエクステンションの名前>.kext

でロードし、

$sudo kextunload <作成したエクステンションの名前>.kext

でアンロードできる。

ほかには?

他にもどうやら

・USBデバイスドライバとか
・ファイルシステムドライバとか
・ネットワークドライバとか

作れるらしい???

参考文献:
https://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/KernelProgramming/style/style.html
OSX and iOS Kernel Programming,Apress, chapter 3

mikutterにTCPソケットサーバ立ててみる

mikutterにTCPソケットサーバを立ててほげほげしてみようと思い立って一気に書き上げました。

発端

ぺんぎんさん(@penguin2716)がmikutterでTCPソケットサーバを立てて、
AndroidをTCPソケットのクライアントにしてつぶやいてみてるのを見かけたのが発端。

TCPソケットのポートは3939(みくみく)にしました。

書いたもの

大体このへんに↓
https://github.com/cosmo0920/MikuTCPConnect

Windows用のTCPソケットクライアントのプログラムをC#+WPFで書いたのがこちら:
https://github.com/cosmo0920/MikuTCPConnect/tree/master/Client_for_Windows/mikuSockCleint

バイナリは同梱してません。
各自でビルドしてください、というのもIPを格納するテキストボックスを作るのを忘れただけなんですが…

mikutterのプラグインになっているのはTCPServerフォルダのものだけです。

他にも
C++(boost::asio)
で書いたTCPソケットクライアント
https://github.com/cosmo0920/MikuTCPConnect/tree/master/Cpp_Client
とか
RubyのTCPソケットクライアント
https://github.com/cosmo0920/MikuTCPConnect/tree/master/Ruby_Client
とか
あります。

通信のプログラムが書けるようになると出来ることが一気に広がりますね!

関西Codersに参加してきました。#KansaiCoders

@naota344さんに誘われたので行ってきました。

濃い話が聞けました。
白のMacBookで窓際の席に座ってカチャカチャやってたのは僕です、はい。

以下僕のツイッターから転載:
1番目の発表

@cosmo__ コスモ
キーリマップの話でした。 #KansaiCoders

2番目の発表

@cosmo__ コスモ
Kinect +Rubyの発表でした #KansaiCoders

3番目の発表

@cosmo__ コスモ
Prologでのちょっとした発表でした。ぱちぱち。 #KansaiCoders

4番目の発表

@cosmo__ コスモ
Androidのセキュリティの話でした。root権限関連は怖いですね #KansaiCoders

5番目の発表

@cosmo__ コスモ
Haskellのモナドの発表でした。ぱちぱち。 #KansaiCoders

6番目の発表

@cosmo__ コスモ
D-Busの発表でした。権限を書き換えられるのは怖いかもしれないけど利便性とトレードオフなのかな。 #KansaiCoders

かなりの方々が集まっていたので発表は興味深く聞くことができました。
また行きたいです。

Xcode4導入の際に

Xcode4をインストールしてみる

Xcode4が出ていたのでApp Storeから購入してみました。
¥600円也。

Xcode4はInterface Builderが統合され、またGitも統合されているようです。

レビュー他に書いている方が居るのでそちらに任せて、この記事では導入の際の注意点をメモしておきます。

Xcode4導入の際に気を付けること

Xcode3.2系と違ってこちらはターゲットがMac OSX10.6以上に限定されます。

リンクエラー発生?

どう言うことかと言うと、同梱されているSDKが10.6向けのものだけしかなく、Mac OSXsdk10.5のライブラリ依存のコンパイラMac OSXsdk10.5に含まれるライブラリを探しに行ってリンクエラーを引き起こします。

例えばHaskellコンパイラのghc(The Glorious Glasgow Haskell Compiler)。

この事を知ったのは@shelacyさんと@tanakhさんのトゥギャッターの指摘からです。

詳しい指摘はリンクからどうぞ。また、ghcフォーラムでの指摘はこちら(英語)。

また、どうやらMac OSX10.6向けのフリーのFortran90/95コンパイラg95Mac OSXsdk10.5を使っているらしくこちらもリンクエラーが発生しました。

対策法

対策として、Developerフォルダの中にSDKsというフォルダがあるのですが、これの中にDeveloper-oldの中からMac OSXsdk10.5となっているフォルダをコピーします。

するとIdの警告は出ますが(Mac OSXのバージョン指定がおかしいという意味?Xcode4では10.6以上しか正規では出来ない為。)、リンクエラーが解消されて正常にバイナリが生成されます。

では。

追記:最新のHaskell Platformではこの問題は解消されています、と同時にMac OSX10.5以前のサポートも打ち切られたようです。