AppleScriptによる並列処理テスト

昨今のMacは最低でも2個のCPUコアを搭載しており、先日発売されたMac Proでは(4×2)からHyperThreadingでさらに1CPUコアが2つのCPUコアに見えるため、16個もコアが存在するように見えるらしい。使ったことがないので「らしい」としか言えないが、5年後ぐらいにはこれが128個などと言っているのだろうか。すごいことだ。 

1つのCPUコアあたりの処理性能も頭打ちになりつつある昨今、CPUコアを増やす方向にコンピュータが進化するのはもう、必然としかいいようがない。たぶん、今後もCPUコアの数が増えることはあっても減ることはないだろう(ノートでは、CPUとGPUによる協調分散処理を指向するということだろうか。MacBook ProにQuad CPUを載せるのは……もうちょっと先の話のようだ。下手をしたらノートでもしばらくはDual CPUどまりかもしれない)。 

こうした大量のCPUコアを活用するためには、並列処理を行うようプログラムを組む必要がある。たとえば、16台のライブカメラからダウンロードした画像が16個のフォルダに分かれて1000枚ずつ保存されていて、それらの画像が壊れていないかどうかチェックするような場合、1つ1つ順番に処理していくのと、16フォルダ並列で同時に処理するのでは、並列処理したほうが処理時間は短くて済むはずだ(ファイルI/Oなど、ボトルネックになる部分があるはずなので、そこ次第?)。 

だが、AppleScriptで並列処理は行えない。マルチスレッド化もできない。アプリケーションのクラスを元にインスタンスを生成するとかいったことも(いまのところ)できない。ないないづくしである。 

厳密に言えば、AppleScriptで作ったアプレット同士でイベントを送り合って処理を行うことはできる。そういう意味での並列処理はできないわけではないのだが、処理の並列性を高めることを目的として、任意の個数のスレッドを動的に生成して処理を行うというようなことはできない。あらかじめ用意しておいたアプレット間で通信を行うだけである。 

UNIXのコマンドシェル経由で同時にAppleScriptの任意の数の処理プロセスを動的に発行できないではないが、そうして起動したプロセスに他のAppleScriptからコマンドを送ることはできない。AppleScript同士のプロセス間通信が行えないのでは、まるっきり意味がない……。 

脱線した。話を元に戻す。シェルではなく一般のAppleScriptの話である。 

できないできないと言うばかりでは進歩がない。そういう細かい単位で処理ができないのなら、別の方法を考えればいいだけのことだ。 

そんなわけで、ちょっと考えてみた。 

1つの働きを行うScriptのアプリケーション(アプレット)をAppleScriptで作成。こいつを「起動」させるには、Finder上でアイコンをダブルクリックするか、明示的に別のAppleScriptで起動命令を実行すればいい。 

tell application "なんちゃら" 
 launch--とかactivateとか 
end 

こんな感じだ。 

1121737255_171.jpgアプレットは、起動すると1つのアプリケーションとして識別される。具体的にどういう状態かといえば、Dockにアイコンが表示され、Dock上のアイコンをクリックすれば手前に表示される。手前に表示されると、メニューバーはそのアプレットのものに切り替わる。 

ここで、並行して複数のアプレットを起動するにはどうしたらよいだろうか。 

一番安直に考えるなら、アプレットのファイルをコピーしてファイル名を変更し、その状態で起動してやればよいだろう。 

たしかに、コピーして起動すれば……同じ働きを行うアプレットが同時に複数起動しておける。だが、このままではそれぞれのアプレットを特定できない。Photoshopのアプリケーションファイルをコピーして複数のPhotoshopを起動したとしても(たぶんできないが)、では一番手前にいるPhotoshopとうしろに隠れているPhotoshopをどのように識別するのか、はたしてそれは可能なのかという話なのである。 

結論からいえばできない。コピーしただけではみーんな同じ名称のアプリケーションとして識別されてしまうからだ。厳密にいえば、プロセスIDを取得してそれぞれのプロセスを番号で区別する方法がないわけではないのだが、「プロセスIDを取得して」という段階をクリアできない(どのアプレットのIDを取得するかという特定ができない)ので、結局ダメである。 

そこで、各アプレットが「違うもの」であるという状態を作ってあげれば大丈夫なんじゃないだろうか? 

アプリケーションメニューに表示されるアプリケーションの名称は、アプリケーション内のInfo.plistにある「CFBundleName」で制御されている。そこで、AppleScriptで作られたアプレットの中に入っているInfo.plistファイルに書かれているCFBundleNameを書き換えて起動してみれば、それぞれが別のアプリケーションとして識別されるのではなかろうか。 

やってみた。 

まあ、そんなに何も問題がなかったわけではなかったが、テレビでサッカーのワールドカップ予選を前後半ひととおり応援している間ぐらいの時間はかけたが、実験は成功した。 
1121737255_121.jpg
1つのアプレットのファイルを複数のアプレットにコピーして、それぞれのInfo.plistを書き換えてあげることで、同時に起動しても個別に識別可能になった。10個ぐらいしかテストしていないが、128個でも256個でも大丈夫なはずである。Dockに表示されるのがうっとおしいということであれば、Dockに表示されないようにエントリを書き換えてあげるだけでいい。 

まあそんなわけで、ものすごく即物的にインスタンスを生成し(汗) 個別のプロセスとして起動するという実験を行うことができた。破損画像のチェックぐらいであれば、並列処理するのもそれほど大変な話ではないだろう。 

1121737255_88.jpgそれにしても、なんでこんな実験が必要なのかといえば、たとえばファイルの破損チェックを行ったあとに欠損画像の補完を行ってムービーに書き出して、FTPサーバーにアップロードするとかいう動作は……同時に大量にやりたいものの、個別の処理が何らかの外的要因によってコケる可能性があるからだ。1つのプロセスがコケても、他の処理に影響を与えないような状況を作りたい。そういう用途には、今回のような実験の成果を活用することになるだろう。 

あとは、16個のCPUコアが載っているようなマシンで実際に実験してみたいものだが……どこからか貸してもらえないだろうか(^ー^;;; 

まあ……それぞれのアプレットは別に1台のマシンで動かしておく必要はないので、LAN経由で別々のマシンに送りつけ、LAN経由でイベントを送って実行させるということも簡単に行える。ファイルサーバー上にある画像フォルダを、LAN上の複数台のマシンで手分けして処理してもよいわけだ。 

やはり、こういうのがコンピュータの醍醐味であり、さほど難しいプログラムを組まずにこうした処理が実現できるというのは楽しいものである。

Copyright By Piyomaru Software. All Rights Reserved