GPGPUとOpenACCについて

はじめに

この記事はVoicyアドベントカレンダー17日目の記事です。

こんにちは、ミック ( @mickbare )です。 Voicyではバックエンドの開発を担当しています。

GPUを使った並列コンピューティングをGPGPUといいますが、最近OpenACCという新しい標準が出たので概要を紹介します。

並列コンピューティングの各種 標準について

OpenACCを紹介する前に、他の主要な標準やプラットフォームについてまとました。 登場の順序としては、大体、OpenMP -> CUDA -> OpenCL -> OpenACCです

OpenMP

共有メモリ・マルチスレッド型の並列アプリケーション開発をサポートするために標準化された並列コンピューティングのためのAPIソースコードにディレクティブを挿入することによって並列化を行います。 OpenMPはループの反復処理を自動的に複数のスレッドに分割して並列処理しますが、起動するスレッドの数や、どのようりスレッドに処理を振り分けるかはOpenMP処理系やプログラムの実行環境などの条件に依存します。 OpenMPに対応していない場合にはディレクティブは無視されるため、並列環境と非並列環境でほぼ同等のソースコード利用できることが利点です。

int kernel(char *src, size_t len) {
    // ディレクティブは #pragmaから始まる
    #pragma omp parallel for
    for (int i = 0; i < len; i++) {
        // 並列処理させたいプログラム
        result[i] = a[i]  * b[i];
    }
    return 0;
}

CUDA

NVIDIAが開発しているGPGPUのためのプラットフォーム nvccというLLVMベースの専用のコンパイラやライブラリなどが提供されています。 CUDA C/C++というC言語拡張で記述します。 NVIDIA製のGPUに最適化されていて、ハードウェア性能を最大限引き出せるようになっちえるがNVIDIA製のGPUでしか使えない制約があるのと記述自体が複雑なのが欠点です。

OpenCL

Appleによって提案、標準化団体のクロノスによって策定された、異種混合環境での並列プログラミングのオープンな標準規格とそのAPIOpenCL C/C++というC言語拡張で記述します。 組み込みシステム向けにはOpenCL Embedded Profileがあります。 CUDAがNVIDIA製のGPUしか対応しないのに対し、OpenCLAMDGPUにも対応していたり、GPU以外での並列処理もサポートするのが利点です。

OpanACCとは

並列コンピューティングための標準の一つ。 クレイ、CAPS、NVIDIA、PGIによって開発されており、世界各地で無料の布教活動を行うなどNVIDIAが本腰を入れて普及させようとしています。 位置付けとしては、CUDA、OpenCLをより標準化したものでOpenMPに近いです。

何が嬉しいのか???

OpenACCは、CUDAがサポートできる一部しか並列化をサポートしない代わりに記述が圧倒的に簡単です。 また、以前は性能差がシビアでしたが、現在は、最適化によってはCUDAよりも高速化できたりと、CUDAと遜色ない性能が出せたという報告が出ています。また、NVIDIAGPU以外にも対応しており、 FPGAにも対応したコンパイラも開発されています。

サンプル

OpenACCではOpenMPと同じくディレクティブを挿入して並列化します。 CUDAやOpenCLのような独立言語ではないので、既存のCPUコードも簡単にGPU化できる。

int kernel(char *src, size_t len) {
    // CPUでの演算対象の指定
    #pragma acc kernels
    # 各ループに対する指定
    #pragma acc loop independent
    for (int i = 0; i < len; i++) {
        // 並列処理させたいプログラム
        result[i] = a[i]  * b[i];
    }
    return 0;
}

終わりに

今からGPGPUを始めるならOpenACCが学習コストが低くて導入しやすいのでおすすめです。 OpenACCで並列プログラミングの勘所を掴んだのち、CUDAやOpenCLに進んでも良いと思います。 GPUによる並列化は機械学習ライブラリでも使用されるので、都度キャッチアップしていきたいですね。

次回は@d_saito2110さんです

Datadogのモニター設定をTerraformのImport機能を使ってコード化する方法

こちらは Voicy Advent Calendar 2021 15日目の記事です。

今年はAdvent Calendarの2本目を書くことになりました。前回は、エンジニアリングマネージャーからテックリードに戻ってみて役に立った3つの考え方を書きました。 この話の中で取り上げた中でTechnlogyManagementの仕事の中心で、最近の仕事ではDatadogの監視設定をTerraform化する作業をもくもくとしていたので、ちょっと便利だった機能をご紹介します。

続きを読む

設計原則をデザインパターンで考える

はじめに

こちらは Voicy Advent Calendar 2021 13日目の記事です。

はじめまして、株式会社Voicyでバックエンドエンジニアをしているなだまるです。

みなさん、設計してますか? 「設計」っていうと難しいこと考えがちですが、普遍的に言われていることを組み合わせてみてみると、あ、こんなもんかと思ったりします。

今回はそんなアプリケーションの設計に関するお話をしてみます。

設計の原則

広く知られる設計の原則として、SOLID原則があります。

この原則の目的は主に以下のような性質を持つ中間レベルのソフトウェア構造を作ることです。

  • 変更に強いこと
  • 理解しやすいこと
  • コンポーネントの基盤として、多くのソフトウェア・システムを利用できること

SOLID原則は以下の各原則の頭文字をとってSOLIDです。 今回は各原則について詳しくは記述しませんが、軽く紹介までに。

  • Single Responsibility Principle(単一責任の原則)
  • Open-Closed Principle(オープン・クローズドの原則)
  • Liskov Substitution Principle(リスコフの置換原則)
  • Interface Segregation Principle(インターフェイス分離の原則)
  • Dependency Inversion Principle (依存関係逆転の原則)

これらだけ読んでも「ほうほう」くらいはなるんですが、具体イメージは湧きづらいですよね。

デザインパターンと合わせて考える

ここで言うデザインパターンGoFデザインパターンを指します。 デザインパターンは23種あり、よく出会う問題とそれに対処する良い設計としてまとめらた指針のようなものです。 こちらの各パターンの紹介も今回は割愛しますが、前半で紹介した原則と合わせて理解することで、どういったところに肝があるのかを掴みやすくなります。

本記事はこの部分を扱います。 説明にクラスと言う言葉を使いますが、便宜上そうしているだけでモジュール等の一定の実装のかたまりの意味合いで捉えてください。

単一責任の原則とFacadeパターン

単一責任の原則はざっくり言うと「モジュールを変更する理由はひとつにすべきだ」というヤツで、ユースケースのアクターが異なるのであればコードは分割しましょうねということです。

Facadeパターンはモジュールの窓口を担う、システムの外側に対するシンプルなAPIを提供するパターンで、クラス図にすると以下のようなものです。

f:id:natacon:20211213223702p:plain
Facadeパターン

Facade パターン - Wikipedia

実装コードを扱うクラスがあったとして、それぞれアクターが異なるメソッドが実装されているとします。(例が雑でごめんなさい) implement()は実装者、review()はレビューする人、release()はシステム管理者が行うとします。 このままだとどういうユースケースの変更であったとしてもCodeクラスを変更することになります。

f:id:natacon:20211213223845p:plain

アクターが異なることがわかっているので、アクターごとにクラスを分けてます。

f:id:natacon:20211213223956p:plain

分けたら分けたで、利用者側からは3つのクラスを意識して上手に使ってあげないといけなくなります。 それは使いにくいので窓口としてFacadeクラスを配置します。

f:id:natacon:20211213224014p:plain

こうすることにより、実装者にかかわる変更はImplementerのみを変更すれば良くなり他のアクターのケースは影響を受けません(関数のシグネチャーが変更される場合などはFacadeも変更対象になります)。

このように、Facadeパターンを通じて、ユースケースのアクターごとに変更すべきクラスを分けることができ、かつ理解もしやすくすることができます。

依存関係逆転の原則とAbstract Factoryパターン

依存関係逆転の原則は、ソースコードの依存関係を抽象だけを参照するようにして、その名の通り依存関係を逆転させるヤツです。抽象クラスやインターフェイスに依存しましょうってことですね。

Abstract Factoryパターンは直訳すると「抽象的な工場」で、これだけだと意味が分かりづらいですが、工場で生産する部品の具体には触れず、インターフェイスだけを使って部品を組み立て製品にまとめようぜというヤツです。APIを定義するイメージですね。クラス図で表すと以下のようになります。

f:id:natacon:20211213224045p:plain
Abstract Factoryパターン
Abstract Factory パターン - Wikipedia

上側がAPIになっていて、下側に詳細の実装が配置されています。

ClientはProduct1のインターフェイス経由でConcreteProduct1を使用します。 Product1はAbstractFactoryインターフェイス経由ででProduct1を生成します。 このとき、AbstractFactoryの実装はConcreteFactoryで実装されていて、この実装がConcreteProduct1のインスタンスを戻す形になっている。

真ん中にアーキテクチャの境界を意味するものとして一本線を引いてみると見通しが良くなります。

f:id:natacon:20211213224137p:plain

この線を横切る依存性はすべて具象側から抽象側に向かっています。 この曲線を横切る処理の流れは、依存性とは逆向きになるため「依存関係逆転」と呼ばれてるんですね。

最後に

今回は設計原則をデザイパターンで考えてみました。

概念をざっくり理解したものについて、違う観点・粒度を合わせ絵考えてみると理解が深くなったりします。 こういう点と点を"意識的に"つなげにいく活動を今後も続けたいですね。

さて次はAndroidエンジニアの @horitamon さんです!お楽しみに!

Web Speech APIの音声認識を使ってWebページを作ってみる

Voicyアドベントカレンダー2021 12日目の記事です。

はじめに

こんにちは、学生インターンとしてVoicyのWebフロントエンド開発をしている、きーくん(komura-c)です。

みなさんは、手を使わず音声でブラウザを操作したいなと思ったことはありませんか?僕はあります。それを実現する手段の一つとして、音声認識があります。この記事は、現状のWeb技術においての音声認識で、自分でもできそうな技術を使ってみようといった趣旨の記事です。

Webブラウザ上での音声認識について調べてみるとTensorflow.jsか、Web Speech APIが出てきます。今回は、機械学習のモデルを用意せずとも日本語で音声認識ができるWeb Speech APIを使ってみました。

Web Speech APIとは

Web Speech APIは、音声合成(Text-to-Speech)と非同期音声認識(Asynchronous Speech Recognition)の2つをウェブアプリに組み込むことを可能にするブラウザのAPIです。

developer.mozilla.org

このAPIは、Web技術の標準化団体W3Cのコミュニティグループの一つであるWICGが策定しており、現在はドラフトの段階で実験的な機能となっています。

各ブラウザの対応状況は、以下の通りです。

https://caniuse.com/speech-recognition

自分で試した環境では、GoogleChrome(MacOS)とSafari(MacOS, iOS)で動きました。

Web Speech APIを使ってみる

今回は、音声認識の方を使い、実際に以下のコードを書いてみました。 (TypeScriptで書きたかったため若干型が書いてありますが、ネイティブのJavaScriptでも変わりません)

https://github.com/komura-c/web-voice-recognizer/blob/main/src/scripts/index.ts

  // ブラウザAPIのインターフェースを取得
  const Recognition = window.SpeechRecognition || window.webkitSpeechRecognition;
  const recognizer = new Recognition();
  // 言語設定を日本語に
  recognizer.lang = 'ja-JP';
  // 解析中の結果を表示する
  recognizer.interimResults = true;
  // 認識のたびに継続的に結果を返す
  recognizer.continuous = true;
  ...
  // 結果表示用のHTML要素を取得
  const resultDiv = document.getElementById('js-result');
  let prevResultText: string;
  recognizer.onresult = function (event) {
    const results = event.results;
   // 中でも最終的な確実性の高い結果を取得
    const resultText = results[results.length - 1][0].transcript.trim();
   // interimResults, continuousをtrueにすると素早く多くの結果が返ってくるため、一つ前と同じテキストは弾いている
    if (prevResultText === resultText) {
      return;
    }
    prevResultText = resultText;
    console.log(resultText);
    resultDiv.textContent = resultText;
    actionByResult(resultText);
    startRecognizer();
  }
  ...

やっていることは単純で、SpeechRecognitionという用意された音声認識サービス用の制御インターフェイスを利用して、startやstop、各イベント後の処理を書いています。

SpeechRecognition - Web API | MDN

音声ボタンを再度クリックして止めるまで認識し続けたかったため、認識完了後も再度認識させるようにしています。

公開したWebページは以下です。

https://komura-c.github.io/web-voice-recognizer/

f:id:komura_c:20211213044538p:plain

初めは音声認識をトリガーにして何らかの動作を行うこと、例えば、ブラウザを操作できたら良いなと考えていたのですが、音声認識により受け取った文字を正しくハンドルすること、解析することが結構難しいなと考え、文字起こしだけのページになりました。この辺は、形態素解析など自然言語処理と組み合わせて一緒に使ってみるともっとできることは増えそうだと思いました。

一応GoogleChrome拡張機能も作ってみました。 拡張機能のボタンを押すことで、上、下という音声を認識してブラウザ上でスクロールを行うことができます。 拡張機能として公開してはいないのですが、以下のコードをダウンロードし、extentionフォルダをchrome://extensions/にあるパッケージ化されていない拡張機能を読み込むで指定すると、使ってみることができます。自分なりに色々カスタムして遊んでみると面白いかもしれません。

github.com

Web Speech APIのさらに深い仕様については、以下の仕様書が公開されています。

https://wicg.github.io/speech-api/

終わりに

Webブラウザ標準のAPIで音に関するものは多くあるので、今後も追って試していきたいと思いました。

おまけ

今回、Chrome拡張機能の作成も視野に入れていたため、React, Vue, AngularなどのSPAフレームワークをあえて使わずに、実行環境を整えるためにParcelを使いました。

https://ja.parceljs.org/

Parcelは設定不要なWebアプリケーションバンドラーを謳っており、Webpackなどと違い設定ファイルが不要ですぐに開発環境が用意できます。 以前Parcelを使ったことはあったのですが、こういった複雑なアプリケーションではない使用用途にはとても体験が良かったです。

ics.media

最近のRustとOSの状況についてざっくり紹介

はじめに

こちらは Voicy Advent Calendar 2021 10日目の記事です。

Rustは近年、Stack Overflow Developer Surveyで「最も愛されているプログラミング言語」らしいです。

リソース管理に所有権という独特の機能があったり、マルチパラダイムで機能も豊富なので学習難易度は高いですが、C++に似た構文でかけ、C言語と同等速度で実行でき、かつメモリ安全性が保証されいます。

C++のメモリの管理は色々気にしないといけないことが多いので、早くてメモリ安全というとC/C++に起き変わりそうな予感がして、俄然習得意欲が沸いてきます。

C/C++が長らく独占している領域といえば、とりあえず浮かぶのはOSですが、今回は、RustとOSの状況について少し調べたことを紹介します。

続きを読む

エンジニアリングマネージャーからテックリードに戻ってみて役に立った3つの考え方

こちらは Voicy Advent Calendar 2021 9日目の記事です。

こんにちは、Voicyの元エンジニアリングマネージャーで現テックリードのみっきーです。2020年1月に入社して紆余曲折があり、2020年8月からはテックリードの役割で働いています。 紆余曲折な出来事は、人事勝村がAdvent Calendarの6日目の記事モチクラ偏差値47だったVoicyがAAA獲得までにやった5つのことで書かれており、 いろいろ会社に変化があったのでご興味がある方はこちらを読むのをオススメします。個人的な変化は会社のブログで書くのもアレなので気になる方はMeetyでお話しましょう。

本記事では、一度会社でマネージャーになると、現場に戻る道がたたれ、再度新しい技術を習得するには、転職するしかない!と考える人に向けて今後のキャリアの参考になることを書きました。 数多くの面接をしていると、転職理由の中にマネージャーになってしまい技術力が足りなくなると思い、このままエンジニアとしてのキャリアが詰めないと考えて転職する方が少なからずいます。 自分もマネージャーからエンジニアに戻るキャリアチェンジを複数回しているので気持ちはよくわかります。最近、巷では、エンジニアリングマネージャーからIC(Individual Contributor)にキャリアチェンジになることも話題になりました。

私も40代間近のシニアエンジニアですので、40歳以降のキャリアを考えるきっかけにもなりました。新卒からWeb開発をしてもう16年、最新のテクノロジーの進化に対して自分の技術の伸び悩みには強く共感しました。ICはメンバーの管理責任を追わない専門職の従業員のことだそうです。会社によってはテックリードと呼ばれていることもあると思います。管理者ではないとはいえマネージメントの仕事がすべてなくなってコードだけを書いているわけではなく、マネージメント対象の割合が変わったと考えるのが適切です。そして、マネージメントと一言で言いがちですが、実際はいくつかに分けることができます。自分がマネージメントをするときに、非常に参考になったnoteのマガジンにVPoE Handbookというのがあります。この中ではVPoEの仕事は4つに分解しています。VPoEとは、エンジニアリング部門のマネージメント責任者で、会社にCTOがいる場合は、テックとピープルのマネージメントを分けたりします。

  1. Project Management
  2. Process Managmenet
  3. Team Build
  4. People & Culture Managemenet

これらはVPoEに必要な役割として定義されており、自分の経験の中でマネージメントに必要な役割は5つに分類しています。

  1. Project Management
  2. Process Managmenet
  3. Team/People Management
  4. Culture Management
  5. Technology Management

それぞれ

  • 1は、目標どおりに機能などをリリースするために開発計画を立て期限までに実行すること。
  • 2は、開発の生産性やデリバリー速度をあげるために、標準化や仕組み化をおこない改善すること。
  • 3は、採用したエンジニアのチームの配置、仕事のアサイン、採用、育成すること。
  • 4は、エンジニア組織の文化づくり。最近だと社内勉強会や輪読会、テックイベントの開催、テックブログ執筆などでお互い切磋琢磨できる仕組みを作ること。
  • 5は、技術負債の返済、技術標準化、技術選定、システム連携など複数のサービスを結合したり、連携したりすること

これらは別のスキルであり、役割によって求められる期待値レベルが異なります。エンジニアリングマネージャやVPoEだと1,2,3,4で特に3と4にかなり時間をさくことが多く、テックリードは5が中心で会社全体の技術に底上げをおこないます。これらは、私は1がかなり苦手で、4,5,3,2,1の順で強みを発揮してきました。CTOになると経営視点にたち全体をバランスよく見ながら、それぞれの役割にもっとも強みを持った人に仕事を移譲できると気持ちも楽になっていきます。今後、マネージメントを学んでいくなかで、エンジニアとしてコードを書き続けるとしても、フリーランスではなく、組織の中で働くことを選んだ人に向けて、なかなか仕事をこなす中では身につきにくいが、意識すると視座が上がることを3つご紹介します。

1. 技術選定と面接は似ている。ソフトウェアのように柔軟に変化する人が活躍する

面接経験は会社が面接担当官に指名しないと経験を積むことが難しいのですが、技術選定は割と簡単に機会を得ることが出来ます。例えば、個人サービスを作ろうと思ったときにどの技術を採用するかは1人でも考えることができるからです。活躍できる人を選ぶことと、自社のサービスにSaaSやライブラリのインストールをしてプログラムに活躍してもらう点では同じ感覚になると思っています。(ただ勘違いしてほしくないのは、優秀な学生を安くバイトで使うという発想になるのはダメです)会社もOSと考えると、OSにソフトウェアをインストールすることと、組織に人を採用することは同じです。どちらも優秀な人/ソフトウェアを入れると、出来ることが増えますし、古い考え方/バージョンが残ったままだと時代の流れに対応できないこともあります。組織にインストールしたときに自らバージョンアップできれば活躍できる機会は増えますし、アップデートできなければ時代の変化に対応できないですが、安定したソフトウェアとして保守される続けることもあるので一長一短です。会社をOSで見たときに、自分がホーム画面に選ばれるようなソフトウェアになれるか、OSとして基盤を支えるものを作っていくかを考えると見方が変わります。マネージャーになることはわりとOSやライブラリを作ることに近く、より高度な技術を磨くためにも一度マネージャーを経験すると良いと思います。

2. コンウェイの法則を意識する

コンウェイの法則とは、「システムを設計する組織は、そのコミュニケーション構造をそっくりまねた構造の設計を生み出してしまう」ことです。「エンジニアリング組織論への招待」などいろんな開発マネージメントの本に出てくる法則です。1つのサービスに閉じて作っていると、拡大していく中で必要な開発人数も多くなるが、人が増えるとコミュニケーションするパスが増えて開発効率は落ちます。最近のマイクロサービス化の流れも、コミュニケーションパスを小さくするために、一つのチームサイズを小さくする必要があり、その結果サービスを分割せざるをえないことになります。システム構造に合わせて組織を作ることをを逆コンウェイの法則と呼び、組織の拡大に合わせて人やソフトウェアを柔軟に変えていく必要があります。より上流工程に関わりたい人は、人を見ることとソフトウェアをうまく分割することの両方の経験が必要になります。そのためにもマネージャーとしてエンジニアリング組織を作るの経験と横断的なソフトウェア開発する経験を2つを意識して経験をつむと良いです。

3. 1人目のフォロワーになる

私の好きなTEDの動画にデレク・シヴァーズさんの「社会運動をどうやっておこすか」があります。ここで大事なことは、1人目のフォロワーになってサポートしていくことです。1人でなにかを始めることは非常に大変ですが、2人が参加すると続いて3人4人と続くことで交代で回せるので継続率を高まります。

1人目のフォロワーとして参加

1回目から参加

自分は起業家としてたくさんの人を引っ張るよりも、投資家として優秀な若手をサポートしていくほうが楽しみを感じるタイプだということが40年間生きてきてわかったことです。 自分がどこに一番熱量を感じられるか体験した上で、ポジションどりがうまく出来ると幸せになれるのではと思いました。

最後に

まだマネージメント経験がなくこれからマネージャーの役割も担いそうな人はぜひ参考にしてみてください。

最後に自分が読んで良かったマネージメントのおすすめの書籍を紹介します。

  • エンジニアのためのマネジメントキャリアパス ―テックリードからCTOまでマネジメントスキル向上ガイド
  • エンジニアリング組織論への招待 ~不確実性に向き合う思考と組織のリファクタリング
  • More Effective Agile ~“ソフトウェアリーダー"になるための28の道標
  • Scaling Teams 開発チーム 組織と人の成長戦略 ~エンジニアの採用、マネジメント、文化や価値観の共有、コミュニケーションの秘訣~

まだ、自分は読んでないですが、どういうチームを作っていくかで最近話題になっている本です。次回、読んだ感想を別の記事に書きたいと思います。

  • ユニコーン企業のひみつ ―Spotifyで学んだソフトウェアづくりと働き方
  • チームトポロジー 価値あるソフトウェアをすばやく届ける適応型組織設計