Macでx10の環境構築

# はじめに

X10という並列処理用プログラミング言語があります。
通常、スパコンなんかではFortranやC,C++でコードを書くことが主流ですが、これらのコードで分散メモリ環境の並列化コードを書くのは結構大変です。
そこで並列処理を容易に書くための言語としてIBM Researchにより開発されているのがX10です。
処理系はオープンソースとして公開されており、ハイエンドのスパコンでの動作実績もあります。

- [wikipedia](http://ja.wikipedia.org/wiki/X10_%28%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E%29)
- [公式サイト](http://x10-lang.org/)

文法はScalaに似ていて、強い静的型付け言語で型推論があり、lambdaも簡単にかけるモダンな言語です。純粋関数型ほどしばりがきつい訳でもないので、そういう点でもScalaに似ているのではないかと感じています。
並列処理のためのシンタックスが追加されていて、例えば `async{ ... }` `finish { ... }` といった書き方で並列処理が記述できます。
PGASというプログラミングモデルを採用しており、複数プロセスでメモリ空間が分割している環境でも、あたかも単一のアドレス空間であるかのように抽象化されています。一方でメモリ空間の局所性を意識したチューニングも可能です。

というわけで文法的には非常に良さそうなのですが、広く普及している言語ではないのでググってもまず情報が出てこないのがツラいです。特に日本語の情報はまずありません。

ここではまずx10のMacへのインストール方法を簡単に解説し、Hello worldプログラムを動かすまでの方法を解説します。

# インストール方法

３種類のインストール方法があります。

1. X10DT（Eclipseプラグイン）
2. ビルド済みパッケージのダウンロード
3. ソースからビルド

### 1. X10DT

まず試してみたいだけならば1のX10DTをインストールするのが手っ取り早いです。Eclipseごとzipしてそのまま使えるものがダウンロードできます。
http://x10-lang.org/documentation/x10dt-installation.html
簡単に動かすにはいいですが、ターミナルからのコンパイル方法とかがわからなかったので、私は結局使うのをやめました。補完も効きません。
シンタックスハイライトとコンパイルエラーのチェックは随時実行されるので、Eclipse嫌いじゃなければ使うのも悪くないと思います。

### 2. ビルド済みバイナリのインストール

おすすめは2の方法です。ビルド済みのコンパイラを手元に持ってきます。
http://x10-lang.org/software/download-x10/latest-release.html
から最新のMac版のビルド済みバイナリを持ってきます。展開したディレクトリの中の bin/ にコンパイラがあるので、そこにパスを通せば使用できるようになります。
`export PATH=$HOME/work/x10/bin:$PATH` を.zshrcとかにかいておけばOK。

私の場合、エディタはvimを使っています。vimでX10のシンタックスハイライトをするために以下のプラグインを入れました。
https://github.com/evandrewry/vim-x10
Vimのプラグイン管理にNeoBundleを使っている場合、.vimrcに `NeoBundle 'evandrewry/vim-x10'` を追加しましょう。

誰かbrewでインストールできるようにしてくれないかな（他力本願）

### 3. ソースからビルド

3はadvancedな方法です。カスタマイズなどをしたい場合にソースからコンパイルをする必要があります。
やったことありません。

# Hello World

はじめてのX10。Hello worldは以下のようになります。

```Hello.x10
import x10.io.Console;                              // C++でいうところの #include <iostream>

class Hello {                                       // クラス名はファイル名と同じでなくてはいけない
  public static def main(args:Rail[String]):void {  // staticメソッドとしてmainを定義
    Console.OUT.println("Hello, world");            // 標準出力にプリント
  }
}
```

（↑シンタックスがハイライトされない。。。）

コンパイルするには`x10c++`コマンドを使います。

`x10c++ Hello.x10`

c++と書いてあることからわかるように、x10をC++に変換して、そのC++を実行ファイルにコンパイルしています。これはNative版と呼ばれています。
実際にコマンドを実行してみると中間の.ccや.hファイルができているのがわかると思います。

他方、c++ではなくjavaに変換することもでき、その場合JVM上で実行することができます。これはManaged版と呼ばれます。Javaの関数を呼ぶことができます。特にJavaの関数を呼びたい時以外はnative版だけ使えばよいと思います。

コンパイルすると実行ファイルができるので、それを普通に実行します。`./a.out`

```shell-session
$ ./a.out
Hello, world
```

# 並列Hello World

せっかくなので並列プログラムでHello worldしてみます。

```ParallelHelloWorld.x10
import x10.io.Console;

class ParallelHelloWorld {
  public static def main(args:Rail[String]):void {
    for (p in Place.places()) {
      at (p) {
        async {
          Console.OUT.println("Hello, I'm " + here);
        }
      }
    }
  }
}
```

**place** というのは、各プロセスに対応します。
**at** は「このplaceで実行してください」という構文で、**async**は「非同期実行しなさい」という意味です。

これをコンパイルして実行します。コンパイルは先ほどと同様です。

```shell-session
$ x10c++ ParallelHelloWorld.x10
$ X10_NPLACES=4 ./a.out
Hello, I'm Place(0)
Hello, I'm Place(1)
Hello, I'm Place(2)
Hello, I'm Place(3)
```

実行時に環境変数 ***X10_NPLACES*** でプロセス数(place数)を指定できます。（指定がない場合は１になるようです。）
今回はたまたま0,1,2,3と順番に出力されていますが、順番に出力される保証はありません。

ちなみにX10の問題ではないですが、macでファイアウォールをオンにしていると以下のようなダイアログが出ます。

![image](https://qiita-image-store.s3.amazonaws.com/0/28792/8be40d6f-26e5-dbcc-cd61-1a5ca3904957.png)

ビルドするたびに出るようになるので鬱陶しいのですが、抑制する方法がよくわかりません。（ファイアウォールを切るのが一番手っ取り早いですが）

ここではプロセス間通信にはsocketが使われています。
通信ライブラリにはMPIなど、他の手段を使うこともできます。