これからのプログラマーに『並列処理』の知識は必須か?

   

「CPU単体の処理性能の向上が限界に来ている」という話を何年か前から聞くようになりましたよね。

昔はCPUがPetium2 → Petium3 → Petium4とバージョンアップされる度にクロック周波数が266MHz(メガヘルツ)から533MHzになるなど、常に上がり続けていましたが、最近は3GHzとか4GHzくらいで止まっていますよね。

その分CPUのコア数が増えていて、Core2Duoでコアが2つになり、Core-i5で4つのコアが搭載されるようになりました。

周波数は伸びてなくても、コアの数が増えているので、複数の処理を複数のコアで同時並行で処理できるようになり、それによってスピードアップが図られています。

ムーアの法則と言って、「シリコン集積回路の集積密度が2年でほぼ2倍になる」と以前は言われていました。簡単に言うとコンピュータの性能は2年間で2倍にアップするということです。

しかし、CPUがあまりに高度に集積されるようになり、これ以上単体での性能アップは無理だという段階になってしまったのです。

ですから、CPUのマルチコア化に対応したプログラムの書き方が出来ないとプログラムの処理性能を上げることは出来ないと言われているんです。

この点について、じっくり考えてみたので紹介します。

Ruby開発者まつもとゆきひろさんの意見

これについて、Ruby開発者のまつもとゆきひろさんが「ソフトウェア開発にフリーランチは存在しない」と言っています。

フリーランチってタダ飯のことです。今まではプログラムを一度書けば、ハードウェアの性能が上がるから年々勝手に動作速度が速くなっていくというタダ飯(プログラムを何も修正しなくても速くなる)を食えたのですが、それがCPU単体の処理性能が限界に達したため、並列に動作するように書き直さないと処理性能があがっていかなくなってしまったのです。

これと、ここ数年関数型言語が注目されていることには関係があります。

関数型言語は並列処理に向いている?

関数型言語は副作用のないプログラミングがしやすいという特徴があるため、並列処理がしやすいんです。

副作用のないプログラミングとはどういうことかというと、関数の動作が関数の外側にある変数に依存しないということです。

オブジェクト指向でいうと、クラスのメンバー変数(フィールド)をメソッドから参照しているようなコードは副作用のあるコードなんです。

状態を持った変数によって、関数の動作が変わってしまう場合、その関数を並列で実行することが出来ません。

しかし、関数が引数にだけ依存している場合は、その関数を並列で処理することが出来ます。

なぜならば、引数とローカル変数はその関数内でしか参照されないからです。

例えば、for文の中でfunc1という関数を呼び出しているとします。この時、func1の動作が外部の変数に依存しないのであれば、for文を順番に繰り返すのではなく並列で処理することが出来ます。

関数型言語で書くと、外部の状態変数に依存しない書き方になりやすいので、プログラマーが並列を意識してコードを書かなくても、言語の処理系が並列に実行できる部分は並列に実行してくれるんです。

例えば、for文で4回処理を繰り返していて、CPUコアが4つある場合、くりかえし一回の処理を1コアに割り当てれば、4つコアがあるので、4回の繰り返しを並列で一回で処理できる場合があるのです。

意識的に並列処理を書くとかなりめんどい

プログラマーが意識して並列処理をさせるコードを書く場合は、for文の中の処理をひとつひとつThred起動して実行させればいいのですが、並列で起動したスレッドが全部終わるのを待つjoin処理なども書かなければなりません。

先程のJavaScriptのコードをJavaで並列に実行するコードを書いた例を示すと以下のようになります。(new Thread(num1, num2)の部分が正確ではないコードです。簡略化してあります)

コードも複雑になりますし、可読性も落ちます。

サーバーは元々並列処理してるからプログラムはそのままでOK

WebアプリやJSON APIなどサーバーサイドのプログラムの場合、1リクエストを処理するプログラムを私たちは書きますよね?では、その1リクエストを処理するプログラムの中でさらにユーザースレッドを起動して処理を並列に動かす必要があるでしょうか?ないですよね。

なんでかというと、サーバー自体が並列で動いて同時アクセスをさばいているからです。

例えばCPUが8コアあるサーバに10個の同時アクセスがあったとします。

その1リクエストの中の繰り返し処理を並列で8個のCPUコアに割り当てて並列処理をさせることになります。

そんなことをしたら、1リクエストで8コアすべてを使ってしまうので、他のリクエストがCPUを使用できなくなってしまいます。(厳密に言えばCPUをタイムシェアリングしてるから、CPU割当が短時間で切り替えられるとは思いますが)

このような理由から、サーバーサイドのユーザープログラムの中では、並列処理を意図的に起こす必要性はないのだと思います。サーバー自体が並列でリクエストを処理しているのですからね。私達が書くユーザープログラムに制御が移る時には既に、プログラムは並列で動いているということです。

具体的に言えば、Apacheからmod-phpだったり、Nginxからphp-fpmに処理が移ってユーザープログラムを起動する頃には、既に並列で起動されてるということです。

ですから、サーバーサイドでは並列処理を意識する必要性はないのでしょう。

ただ、クライアントサイドでは状況が違ってきます。

クライアントサイドは並列処理の意識が必要?

私のキャリアはサーバーサイドが中心なのですが、短期間ながらスマホゲームのクライアント側の開発をしたことがあります。

ゲームのクライアント側ってすごく並列的に動いているんですよ。

フレーム処理というものがあって、一秒間に30回画面描画が走ることを30fps(frame per second = フレームレート)と言います。

それくらい細かい描画処理をしながら、裏でサーバーのAPIと通信してたり、ローカルストレージにデータを保存したりします。

こういう風にクライアント側は並列を意識してコードを書く場面があるのかなと思います。スマホのCPUもマルチコアですからね。

とはいえ、これらの処理はゲームエンジンなどの下のレイヤーでGPUをうまく使うなどを勝手にやってくれるのでしょうから、やはり、クライアントサイドにおいても、アプリケーションプログラマーが並列処理を意識する必要性はほとんどないんじゃないかなと思います。

まとめ

そんなわけでここ数年並列処理の重要性が言われていますが、実際それを意識したコードを書く機会がないなぁと感じています。まぁ、私が書いてるコードはアプリケーションのコードなので、もう少し下のレイヤーを開発している人だと全然違った状況なのかもしれませんけどね。

エージェントを使った方が転職活動は楽です

東京・大阪近郊のイケてるIT企業に転職したい人には『レバテックキャリア』

 東京・大阪近郊のエンジニア経験者向け転職サービスです。

このサービスを運営しているレバレジーズという会社はシステム開発もやっているので、現場の仕事をよくわかってくれてますし、ヒカ☆ラボというIT系の勉強会なども主催していたりteratailというプログラマー専用の質問サイトを運営してて好感が持てます。求人案件もWebやスマホの面白い仕事が多いのでいいと思います。

あとホームページ見ると分かるんですが、若くて美人の担当者が多いのもナイスなんです!私の場合(たぶんあなたも)、担当者が美人だと転職活動のモチベーションめちゃ上がりますからね笑

エンジニア未経験の方や地方在住の方にはDODAというエージェントをおすすめします。

エンジニア未経験の方や地方在住の方には『DODA』

全国の求人を扱っていて、しかもITエンジニア未経験の人にも転職支援をしてくれるエージェントです。

未経験の人はサポート対象外のエージェントが多い中、DODAは未経験者を支援し転職を成功させています。未経験の方こそエージェントから職務経歴書の作り方や面接の仕方のレクチャーを受けた方がずっとうまくいきます。

フリーランスになりたい人には『ギークスジョブ』

フリーランスエンジニアになるには人脈が必要と思われがちですが、ギークスジョブに登録して希望条件を伝えれば、自分に合った案件を紹介してもらえるんですよ!思ってるより全然簡単にフリーランスってなれるもんなんです。

東京・大阪・名古屋・福岡の案件を紹介してもらえます。

 - 技術