GCDが、バックグラウンドで処理するとか処理が速くなったとか、あーだこーだで、マルチタスク(マルチスレッド)のイメージが強かったのですが、思ってたものと違った件
マルチタスクとマルチスレッド
だいたい同じものと思ってるのですが、自分流では マルチタスクとマルチスレッド関連定義はこう
-
タスク = 大きな処理単位
-
スレッド = タスクより小さい処理単位
-
シングルコアCPU = プロセッサコアが1つのCPU
-
マルチコアCPU = プロセッサコアが2つ以上のCPU
-
マルチタスク(シングルコアCPU )
-
スレッドを切り替えて同時進行させる方式で,プリエンティブ方式とノンプリエンティブ方式がある。
-
プリエンティブ方式(preemptive multitasking)
-
時間で強制的にスレッドの実行が切り替わる、各スレッドを時間で切り替える方式
-
ノンプリエンティブ方式(nonpreemptive multitasking)
-
スレッドの都合(待ち時間等)で別のスレッドに処理を切り替える方式
-
マルチタスク(マルチコア CPU )= スレッドをCPUで分けて同時進行させる。
コア数以上の処理を実行するためには、コアをプリエンティブまたはノンプリエンティブ方式で実行させる必要がある。- インテルCPUではハイパースレッディング・テクノロジーといって CPU処理単位でノンプリエンティブ方式の様な事して、CPUバス,パイプライン等の待ち時間を減らして処理を速くしているんです。そんなコアが複数あるなんて・・すごいですね。
-
マルチスレッド
- マルチという限りスレッドを並行実行する機構を備える必要があるのですが、どれくらいの時間単位を並行と呼ぶのか、そこが曖昧なんです。昔は十分に速い単位などと言ってたし、CPUのコア1つの時代だったんですが、マルチタスク/マルチスレッドの言葉だけはありましたからね・・
- スレッドがすごく早い時間(ここポイント) で、プリエンティブ/ノンプリエンティブ方式関係なく複数動作すれば、マルチスレッドであると思います。ただし、ノンプリエンティブ方式で、スレッドが確実に早い時間(ここポイント)以内に切り替わる保証が必要があると考えます。まぁマルチと言うのにスレッド1つハングアップしたらスレッドが切り替わらないで、皆さん一緒にハングなんては、認めませんけどね。
(大昔のWindows/Macは、ひとつ死んだらみんな死んだ。)
で、多くのスレッドが速い時間で切り替わって動作するもんだと思ってた。
はじまり
マニュアル読まずにあーだ、こーだとアイデアとコピペでGoogleさん頼りで、
(GCD)で処理を複数作った時に iphone5s(A7コア/ios8),ipod6th(A8コア/ios9)は、動作したのですが、ipod4th(A4コア/ios6)で動作しないGCDがあった事が発端。
内容はこう
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{}); こいつを使って、並行処理(長い時間処理)をしている。
1つめは動作した。
1つめ動作中に2つめを動作させたら止まっているようだ。
どうもGCDの実行数に制限があるようだった。(マルチスレッド数に制限??????)
いくつまで実行できるのかな?
調べる
-
Googleさんにきいたら、GCDのキューに入ったタスクを複数のスレッドがが処理しているらしく
このスレッドの数はコア数で勝手に決まるらしい。(ふむふむ) -
appleさんの並列プログラミングガイド( https://developer.apple.com/jp/documentation/ConcurrencyProgrammingGuide.pdf )によると、
"Grand Central Dispatch(GCD)のディスパッチキューは、タスクを実行するためのツールとして、強力な機能を持っています。ディスパッチキューを使えば、任意のコードブロックを、呼び出し元と非 同期的に、あるいは同期的に実行できます。独立したスレッド上で実行していたようなタスクは、 ディスパッチキューを使っても、ほとんどすべて実行できます。しかも、スレッドを使う方法に比 べ、より使いやすく効率もよい、という利点があります。"
私的には、”GCD って、すごいんだーどうだー的に見える。(まぁすてき)
その上、なにげなく
"並列ディスパッチキューは、並列に実行できる複数のタスクがある場合に有用です。並列キューも キューの一種なので、タスクは先入れ先出しの順序で取り出されます。しかし、前のタスクが完了し ていなくても、次のタスクを取り出せるのが特徴です。同時に実行可能なタスク数は可変で、アプリ ケーションの状態に応じて動的に変わります。この数を決める要因として、プロセッサのコア数、ほ かのプロセスが実行した処理量、ほかの直列ディスパッチキュー上にあるタスクの優先度など、さま ざまなものが関与します。 "
つまり、同時実行できるよ。しかし実行可能なのはハードウエアやアプリ、IOSバージョンで変わるって事かな?(で・・いくつ?) -
ipod4thのA4はシングルCPU、iphone5sとipod6thはデュアルCPUである。
シングルCPUであってもmainと1スレッドは動いていたからマルチスレッドができてないわけではない。
残念なことに、具体的な数はみつけられなかったです。
実験
環境
Xcode 7.2
内容
ディスパッチキューに100コ無限ループ投入していくつ実行されるか?
プログラムを20回実行する
対象
ipod4th (A4コア/ios6)
iphone5s (A7コア/ios8)
ipod6h (A8コア/ios9)
-(void)viewDidLoad {
[super viewDidLoad];```
// Do any additional setup after loading the view, typically from a nib.
short i;
for(i=0;i<100;i++)
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
NSLog(@"%d実行",i+1); while(loopFlag){}
});
}
[NSTimer scheduledTimerWithTimeInterval:10.f
target:self
selector:@selector(hoge:)
userInfo:nil
repeats:YES ];
}
-(void)hoge:(NSTimer*)timer
{
NSLog(@"停止します");
loopFlag=0;
[timer invalidate];
}
結果
- コア数で実行された数は、決まっていない
- 動的に変化してる(appleさんの言うとうり)
- ipod4th(A4コア/ios6)では、予想どうり多くのGCD処理が動いてなかった。
- ipod4th iphone5sのGCD開始に時間がかかる(20コ/100コ 実行された場合に最後のGCD(20コ目)が実行されるのに300msかかってた
結論
- そもそもGCDの使い方が正しいのか不安になった。( キューを順次処理させるワーカーを長時間占有する事 )
- 最近のiphoneなら軽く10コ程度は問題ないでしょう。(処理時間は、重量級になるかも)
- シングルコアの場合は、GCD1コにしましょう。スレッドを待たせるのなら複数でも