— boreal-kiss.com

ベルリン芸術大学の下見も兼ねて、7月末に大学のサマースクールに参加してきました。内容は、ベルリン市内あちこちにある歴史的記念碑が、町中に存在することで人々とどのような関係にあるのかを考察する、というずいぶん抽象的なものでした。ファインアートのコースに分類されてはいたのですが、記念碑そのもの(作者など)に関する勉強会というものではなかったので少し拍子抜けした部分がありました。しかし記念碑の作成に至るまでの経緯や歴史的背景を体系的に学んだことで、自分の物作りの方法論にヒントを見つけたことと、ベルリンそのものについてさらに知ることができたことが自分にとって収穫でした。

ベルリン市内の記念碑は観光客でにぎわっているところが多く、観光客用の情報がネット上に多々あると思います。しかし今回せっかくツアー客以上のことを学べたのだからそのことを文章にまとめておこうと思い、数回にわけてブログに記録することにしました。できるだけベルリンの(アートを含めた)事情が伝わるように書こうと思います。

その第一回ですが、ゲオルグ・エルザー記念碑を紹介します。

SDIM3206

SDIM3212

ゲオルグ・エルザーは第二次世界大戦前夜にアドルフ・ヒトラーの暗殺を企てた人物とされています。彼はヒトラーの演説会場に時限爆弾を仕掛けたのですがヒトラーがたまたま別件で予定より30分早く退場することで暗殺は未遂に終わってしまいました。この暗殺未遂事件については、あと一歩で歴史を変えるところだったというのが一般の見解のようです。

1939年11月8日、ヒトラーは、かつてミュンヘン一揆の舞台となったビアホール「ビュルガーブロイケラー」で、毎年恒例であったミュンヘン一揆16周年記念演説を行った。この年、ヒトラーはベルリンで行われる第二次世界大戦に関する打ち合わせのため例年より早めに演説を切り上げ会場を後にした。ヒトラーが退席した後、時限爆弾が爆発し、7人が死亡し、63人が負傷した。(Wikipedia)

彼の横顔をモチーフにしたこの記念碑は、彼の英雄的な行動に対して2011年にベルリン州によって建立されました。彼は1945年に強制収容所でヒトラーによって処刑されているのですが、記念碑がヒトラー私有の施設があった場所(Führerbunker)の近くに建立されているという地理的事情も相まって、何か物語性が強く前面に押し出された特異な記念碑に感じられます。

ゲオルグ・エルザー記念碑の位置。ベルリン中心部に位置しているのでアクセスはしやすいと思います。


View Larger Map

夜はライトアップされるようです。

Read More

Processingでちまちま描いていたSimian Mobile Discoの最新アルバム、Unpatternsのカバーアートに採用されました。CD、レコードともに盤を回転させるとカバーの模様と干渉してモアレが生成される仕組みになっていて、ジャケットを鑑賞するだけでも楽しめると思います。元々の図柄はBridget RileyのRiley Wavesを再現したものになっています。

同時にiPhoneアプリケーションの方もコラボレーションさせていただきました。こちらはMoiréアプリの内容にいくつか新しい形状を加えた形になっています。もちろん最新アルバム収録曲全て聴けます。

Read More

テンプレートにサブグループ(グループ内グループ)を追加する方法は、Appleのデフォルトテンプレートには実践している例がなく、さらにテンプレートの仕様についても何も情報がないため長いこと謎だった。が、判明。例えば以下のようなディレクトリ構造のままテンプレートにSomeClass.mファイルを追加したいとする。

Classes/SomeClass/SomeClass.m

この場合、Definitionsパートに次のように記述すればディレクトリ構造を保持したままテンプレートに追加することができる。

<key>Definitions</key>
<dict>
	<key>Classes/SomeClass/SomeClass.m</key>
	<dict>
		<key>Group</key>
		<array>
			<string>Classes</string>
			<string>SomeClass</string>
		</array>
		<key>Path</key>
		<string>Classes/SomeClass/SomeClass.m</string>
	</dict>
</dict>

Nodesパートは関連するKeyネームを追加するだけで特に目新しい変更はない。

<key>Nodes</key>
<array>
	<string>Classes/SomeClass/SomeClass.m</string>
</array>

サブグループを追加したテンプレートの一例はgithubに置いてある。テンプレートの詳細については以下のリンク先を参照ください。

Read More

Xcode 4用のユーザーテンプレートの作り方がだいぶわかってきたのでまとめた。余裕ができたら日本語化する予定。

テンプレートを改変をする際に注意すべきこと

TemplateInfo.plist (新規プロジェクト作成時にXcode 4が最初に読み込む設定ファイル)の改変には細心の注意を。不正なデータ構造を残したままXcode 4に読み込ませると最悪の場合、無関係なディレクトリを消去してしまう等、作業環境に悪影響を与える可能性がある。詳細は上記ブログ記事を参照ください。

Downloads

iPhone用のサンプルは以下に置いてある。

Read More

イントロダクション

Grand Central Dispatch (GCD)にはforループをマシンのコア数に応じて並列処理してくれる便利な関数 dispatch_apply(size_t, dispatch_queue_t, void) が存在する。

void dispatch_apply(
	size_t iterations,
	dispatch_queue_t queue,
	void (^block)(size_t));

引数は前から順番に、forループのイテレーション回数、タスク送信先のキュー、各イテレーションで行われるタスク、である。この関数はforループの各イテレーションごとにキューにタスクを送っている。したがって、もしタスクの処理時間がキューにタスクを送信するためにかかる時間(オーバーヘッド)より小さくなるような場合には注意が必要となる。普通にforループをまわす時よりも処理が遅くなる可能性があるからだ。具体例を見てみよう。

実行環境

Mac OS X 2.4 GHz Intel Core 2 Duo (CPU2個)

forループ vs. GCD その1

以下のような「何もしない」blockをforループでまわして処理にかかった時間を計測してみる。

void (^block)(int i) = ^(int i){
 
};

比較するのは普通のforループ処理を行う関数 loop_normal(int, void)

static void loop_normal(int count, void (^block)(int)){
	for (int i=0; i<count; i++){
		block(i);
	}
}

とGCDを用いた場合の関数 loop_normal_gcd(int, void) である。

static void loop_normal_gcd(int count, void (^block)(int)){
	void (^block_gcd)(size_t i) = ^(size_t i){
		block(i);
	};
 
	dispatch_queue_t queue 
		= dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
	dispatch_apply(count, queue, block_gcd);
}

比較した結果が下図になる(横軸はイテレーション回数、縦軸が関数の処理にかかった時間)。これを見るとGCDを用いた場合の方が(格段に)遅くなっていることがわかるだろう。この原因は「何もしない」タスクを完了するための時間に比べてキュー送信のオーバーヘッドが大きいことによる。

for loop vs GCD

それではこのオーバーヘッドが無視できるような構造にするにはどうすればよいだろうか。ひとつの方法はループにストライドを導入することである。

ストライドの導入

この方式はストライドで定義される整数値分の回数のイテレーションを一回のイテレーションに押し込んでしまう方法だ。これによりforループのイテレーション回数が減り、かわりに一回のイテレーションにおけるタスク量を増やすことができる。具体的に見てみよう。まず普通のforループを行う関数 loop_normal(int, void) がある。これはcount回のイテレーションを行う。

static void loop_normal(int count, void (^block)(int)){
	for (int i=0; i<count; i++){
		block(i);
	}
}

次に上記関数と全く同じ処理を行う関数が以下の loop_stride(int, int, void) である。ただし整数 stride (stride < count) を導入することで関数内部のループ回数が (count / stride) になっていることに注目してもらいたい。イテレーション回数が減った分イテレーション一回のタスク量が増えていることもわかるだろう。

static void loop_stride(int count, int stride, void (^block)(int)){
	int iMax = count / stride;
	int remainder = count % stride;
 
	void (^block_stride)(int i) = ^(int i){
		int j = i * stride;
		int jMax = j + stride;
 
		if (i == iMax - 1){
			jMax += remainder;
		}
 
		while (j < jMax) {
			block(j);
			j++;
		}
	};
 
	for (int i=0; i<iMax; i++){
		block_stride(i);
	}
}

ストライドを導入すればイテレーションの一回のタスク量を増やせることがわかった。それでは実際にGCDに放り込んで結果を見てみよう。

forループ vs. GCD その2

比較したのは普通のforループを行う関数 loop_normal(int, void)

static void loop_normal(int count, void (^block)(int)){
	for (int i=0; i<count; i++){
		block(i);
	}
}

とストライドを導入して一回のタスク量を増やした関数 loop_stride_gcd(int, int, void) である。

static void loop_stride_gcd(int count, int stride, void (^block)(int)){
	int iMax = count / stride;
	int remainder = count % stride;
 
	void (^block_gcd)(size_t i) = ^(size_t i){
		int j = i * stride;
		int jMax = j + stride;
 
		if (i == iMax - 1){
			jMax += remainder;
		}
 
		while (j < jMax) {
			block(j);
			j++;
		}
	};
 
	dispatch_queue_t queue 
		= dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
	dispatch_apply(iMax, queue, block_gcd);
}

そして両者の引数に「何もしない」blockを渡し実行時間を比較した。

void (^block)(int i) = ^(int i){
 
};

ここではイテレーションの回数は100,000回に固定し、ストライドの値を変化させて両者を比較した。結果は以下の図になる(横軸はストライドの値、縦軸は関数の処理にかかった時間)。ストライドの値が大きい場合はGCDを用いた場合の方が処理が早くなっていることがわかる。これらはつまりキューにタスクを送る際のオーバーヘッドが全体として無視できる程度になっていることを意味する。

for loop vs GCD (stride)

まとめ

GCDの恩恵を受けるためにはタスクは適度に重い(処理に時間がかかる)ものである必要があることがわかった。タスクが軽すぎる場合、GCDを利用することでかえって普通のforループよりも処理が遅くなる場合がある。これはGCDのオーバーヘッドによる。このような場合にはforループにストライドを導入することでイテレーション回数を減らし一回のタスクを重くすることで解決できる。

Read More

Grand Central Dispatch

OSX 10.6から導入されたGrand Central Dispatch (GCD)は複数タスクを処理するための便利な仕組みのことで、これを使うとマルチコアの恩恵を簡単に受けることができる。複数同時処理といった仕組みとしてスレッドがあるが、GCDの場合(スレッドを作成する時・制御する時のような)面倒くさい手順を一切踏まなくてよくなる。さらにシステム側でCPUを適切に利用する工夫がされているので(CPU1個なら1個、2個なら2個、8個なら8個勝手に使ってくれる)実行環境を気にしなくてよい、という利点が挙げられる。詳細は以下のドキュメントが非常に参考になる。

さて今回、CPUが複数あるマシンでGCDの恩恵を受けているかどうかを簡単な計算で確認したので以下に結果を載せておく。GCDにはforループを簡単に並列化する仕組みがあるのでそれを利用した。なお計算を行ったマシンは2.4 GHz Intel Core 2 Duo。

forループの並列化

以下のようなforループがあるとする。

for (int i=0; i<count; i++){
	//Do some work.
}

ループ内のi回目の処理が他と独立したタスクである場合GCDのdispatch queueを用いて並列処理が可能になる。以下は上記forループと同じ仕事を行う。

//GCD way.
void (^block)(size_t i) = ^(size_t i){
	//Do some work.
};
 
dispatch_queue_t queue 
	= dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(count, queue, block);

ここで

void (^block)(size_t i)

はblockと呼ばれるApple独自のC言語の拡張である。これは簡単に言うと一連の作業をまとめてオブジェクト化したものであり1、GCDとは親密な関係にある。block自体も簡単で便利な仕組みなので、興味があるひとは以下のドキュメントを参考にしてほしい。

さて上記の場合、blockに記述された内容がforループ内の処理に相当し、これをGCDのdispatch_apply()の引数として渡してシステム側で処理してもらっている。記述が簡単な点にも注目してもらいたい。

計算結果

普通のforループとdispatch queueを用いた場合を比較したものを載せておく。forループ内の1回の処理時間(t_task)を横軸、ループ終了までにかかった時間を縦軸にとってある。ここでループの回数(count)はt_taskの値ごとに異なっており

t_task x count = 10 sec.

となるように設定してある。例えば図の一番左のバーの場合、ループ内の一回の処理時間を0.00001秒、ループの総数を1000000回としてある(全処理時間は0.00001 x 1000000 = 10秒)2。試行範囲に限って言えばdispatch queueを用いた方が2倍ほど早いことがわかる。2倍という数字はCPU2個使った並列化、ということだろう。設定によっては普通のforループの方が早くなるようなことがあるかと思われたがそのようなこともなかったので、並列化が可能であればGCDはどんどん使った方が良さそうだ。

確認用プログラム

上記計算に使用したプログラム。ループ内の処理時間の変更は指定時間スリープさせることで実現させてある。gettimeofday_sec()はマイクロ秒測定用の関数でC言語: 実行時間測定の方法より拝借した。

#import <Foundation/Foundation.h>
#include <sys/time.h>
 
double gettimeofday_sec();
static void test_normal_loop(int count, NSTimeInterval sleep);
static void test_dispatch_que(int count, NSTimeInterval sleep);
 
int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
 
	const NSTimeInterval TEN_SEC = 10.0;
 
	for (int count = 10; count < 1e7; count*=10){
		NSTimeInterval sleep = TEN_SEC / count;
		test_normal_loop(count, sleep);
		test_dispatch_que(count, sleep);
	}
 
    [pool drain];
    return 0;
}
 
double gettimeofday_sec(){
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec + (double)tv.tv_usec*1e-6;
}
 
static void test_normal_loop(int count, NSTimeInterval sleep){
	double t1 = gettimeofday_sec();
 
	for (int i=0; i<count; i++){
		[NSThread sleepForTimeInterval:sleep];
	}
 
	double t2 = gettimeofday_sec();
 
	printf("%f\n", t2 - t1);
}
 
static void test_dispatch_que(int count, NSTimeInterval sleep){
	double t1 = gettimeofday_sec();
 
	void (^block)(size_t i) = ^(size_t i){
		[NSThread sleepForTimeInterval:sleep];
	};
 
	dispatch_queue_t queue 
		= dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
	dispatch_apply(count, queue, block);
 
	double t2 = gettimeofday_sec();
 
	printf("%f\n", t2 - t1);
}

Footnotes

  1. 仕組みとしてはNSInvocationに似ているがblockは特定のメソッドだけに固執しておらず、記述された内容をprocedualに実行できる []
  2. 縦軸のループ処理時間が10秒以上になっているものがあるのはループを行う際のオーバーヘッドの累積によるもの。 []
Read More

例えば、NSProxyのサブクラスにメッセージのフォワーディングをさせたい時1などにどうしてもこの警告が表示されてしまう。存在しないメソッドを呼んでいるので警告が出るのは当たり前だが放置しておくにはうっとおしい。この警告、実は簡単に消すことができる。

Solution

“…may not respond to…”が表示されるクラスのカテゴリを新規に作成し(インターフェイスのみ)、その中に”…may not respond to…”が表示されるメソッドを定義してやる。インターフェイスは”…may not respond to…”が表示されるファイルの一番上にでも書いておけばよいだろう。

Example

以下の例ではMyObjectクラスの-[MyClass doSomething]をメインスレッドで実行する際にNSProxyのフォワーディングを利用している。-[MyObject doSomethingOnMainThread]に注目してもらいたい。-[NSObject performSelectorOnMainThread:withObject:waitUntilDone:]をNSProxyのサブクラス(MyProxy)に送っているがMyProxy ()カテゴリのおかげで”…may not respond to…”の警告が表示されない。

//
//  MyObject.m
//
 
#import "MyProxy.h"
 
//This is important!!
@interface MyProxy ()
-(void)doSomething;
@end
 
@implementation MyObject 
 
-(void)doSomethingOnMainThread{
	MyProxy *myProxy = [[[MyProxy alloc] initWithTarget:self] autorelease];
 
	//No warnings!!
	[myProxy doSomething];
}
 
-(void)doSomething{
	//Does something.
}
 
@end
//
//  MyProxy.h
//
 
#import <Foundation/Foundation.h>
 
@interface MyProxy : NSProxy {
	id _target;
}
 
-(id)initWithTarget:(id)aTarget;
 
@end
//
//  MyProxy.m
//
 
#import "MyProxy.h"
 
@implementation MyProxy
 
-(id)initWithTarget:(id)aTarget{
	_target = aTarget;
	return self;
}
 
//Override
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
	return [_target methodSignatureForSelector:aSelector];
}
 
//Override
-(void)forwardInvocation:(NSInvocation *)anInvocation{
	[anInvocation performSelectorOnMainThread:@selector(invokeWithTarget:)
		withObject:_target waitUntilDone:NO];
}
 
-(void)dealloc{
	_target = nil;
	[super dealloc];
}
 
@end

Reference

Footnotes

  1. メッセージフォワーディングの具体例は-[NSObject performSelector:withObject]に複数の引数を渡す – boreal-kiss.com []
Read More

iPhone、iPad用にアイコンをリサイズするMacアプリケーションIconUtilityをver. 0.9.3にアップデート。画像縮小時の質感のコントロールできるようになりました。具体的にはCoreGraphicsが描画時に使用するinterpolationアルゴリズムを選択できるようにしています1。コアになっているのは以下の関数。

void CGContextSetInterpolationQuality (
   CGContextRef c,
   CGInterpolationQuality quality
);
 
enum CGInterpolationQuality {
   kCGInterpolationDefault = 0,
   kCGInterpolationNone = 1,
   kCGInterpolationLow = 2,
   kCGInterpolationMedium = 4,
   kCGInterpolationHigh = 3
};
typedef enum CGInterpolationQuality CGInterpolationQuality;

CGInterpolationQualityの具体的な使用例はResize a UIImage the right way — Trevor’s Bike Shedで紹介されているUIImage+Resize.h, UIImage+Resize.mが参考になります。

以下IconUtility ver.0.9.3で作成したアイコン例を挙げておきます。

- None (kCGInterpolationNone)を使用した場合のIcon@2x.png

- High (kCGInterpolationHigh)を使用した場合のIcon@2x.png

ソースとアプリケーション本体は以下に置いてあります。

Footnotes

  1. 以前のバージョンではkCGInterpolationDefaultのみを使用。 []
Read More

画像をドロップするとiPhone/iPad用のアイコン用にリサイズするMac用アプリケーションです。対応サイズと出力ファイル名は以下の通り1

  • Icon.png – 57×57ピクセルのiPhoneアイコン
  • Icon@2x.png – 114×114ピクセルのiPhone 4アイコン
  • Icon-72.png – 72×72ピクセルのiPadアイコン
  • Icon-Small.png – 29×29ピクセルのiPhoneセッティングアイコン
  • Icon-Small@2x.png – 58×58ピクセルのiPhone 4セッティングアイコン
  • Icon-Small-50.png – 50×50ピクセルのiPadセッティングアイコン

ソースとアプリケーション本体は以下に置いてあります。

Footnotes

  1. Updating for the iPhone 4 retinal display – Blog – Use Your Loaf []
Read More

» Demo movie for iPad users
» Demo movie for iPhone users

Pscope for iPadはフォトライブラリの写真から万華鏡ライクなイメージを生成するiPadアプリケーションです。Pscopeの名前の由来は「Pentagonal kaleidoscope」です。万華鏡でいうところの鏡の形状が五角形になっているので一般的な万華鏡とは違った雰囲気が楽しめます。五角形の形状は現在知られているパターンすべて(注1)を網羅しておりサイズや形状などの細かいカスタマイズも可能です。さらにスクリーン上のタッチポイントによって描画される画像が変化するので同じ写真素材からいくらでも異なる万華鏡イメージを作り出します。

(注1. 2010.07.02 – 五角形タイルの全14パターンの内、Type 2と呼ばれるものについては現在修正中につきアプリケーション内で使用できません。修正完了までお待ちください)

Demo images

いくつかの有名な五角形タイルを用いて実際に万華鏡イメージを出力させてみました。

- 入力に用いたのは以下の画像 (from [Flash] fla06 – boreal-kiss.com)。

- Cairo pentagonal tilingを用いて描画したもの。

- Floret pentagonal tilingを用いて描画したもの。

- Prismatic pentagonal tilingを用いて描画したもの。

App Storeで販売中

Pscope for iPadは現在230円で販売中です。

アプリケーション詳細はこちら。» Pscope for iPad

参考

Read More