SlideShare a Scribd company logo
1 of 55
Download to read offline
C#JobSystem を使った
Unity流マルチスレッドプログラミング
ユニティ・テクノロジーズ・ジャパン合同会社
エバンジェリスト

伊藤 周
• 今回紹介するC# Job Systemはまだ発展段階
• リリースでは多少の差異が出る可能性がある
• C# Job Systemの概念を知ってほしい
• プログラマ以外は理解不能
諸注意
• 従来のマルチスレッドプログラミング
• C# Job System の概要
• Let’s read codes. (コードを読む)
• Let’s make a mistake. (間違ってみる)
• Let’s try “C# Job Compiler” (コンパイラを体験)
• Let’s implement. (実装してみる)
• まとめ
アジェンダ
従来のマルチスレッドプログラミングの話
マルチスレッド
プログラミングは
好きですか?
私は嫌いです
• レースコンディション対策が嫌だ
• 面倒臭い
• コードが汚い、可読性が低い
• 間違っても気づきにくい
MTPのここが嫌だ その1
Aが使うよ
Aが使うよ
Bが使うよ
A
AB
?
write
write read
• デッドロックが嫌だ
• 面倒臭い
• コードが汚い、可読性が低い
• 間違うと無限ループ
MTPのここが嫌だ その2
A
AB
B
待ち待ち
• 難解なところが嫌だ
• mutex:lockとか
• アトミック変数とか
MTPのここが嫌だ その3
• デバッグが嫌だ
• 正常に”動いてしまったり”する
• 無限ループになったりする
• 突然ハングアップしたりする
• リリース後にバグが判明したりする
MTPのここが嫌だ その4
私には無理だ!
そんなあなたに
C# Job System
C# Job System の概要
43伊藤周の年齢
116
116倍Boid シミュレーションを
マルチスレッドで 8 core CPUで
動かした場合の速度倍
Demo
• 簡潔に書ける
• GCフリー
• 安全
• 高速な新コンパイラ
C# Job System の特徴
• Data Oriented Programming
• データとビヘイビア(振舞い)の分離
• struct(構造体)コンポーネントの導入
• Job Component System の用意
• 簡潔に書けるようにマネージャーを用意
特徴1 簡潔に書ける
• GCをいかにさせないか
• NativeArrayの導入     
• 以下の感じで確保
• 以下の感じで解放(自分で)
特徴2 GCフリー
var src = new NativeArray<float>(500, Allocator.Temp);
src.Dispose();
 要素数 アロケーターの種類
  ↓     ↓
• 他のNativeArrayファミリー
特徴2 GCフリー
struct NativeArray<Value> // 配列
struct NativeList<Value> // リスト。追加削除が容易
struct NativeSlice<Value> // 一部を切り取れる
struct NativeHashmap<Key, Value> // Dictionary「
struct NativeMultiHashmap<Key, Value> //複数Dictionary
• エラーで指摘してくれる
• 落ちることはない
• レースコンディション、デッドロックは起こり得ない
• “Sandbox”
特徴3 安全
• C#→[Mono]→IL→[C# Job Compiler]→内部的な Domain
Model →[最適化]→[LLVM]→実行形式
• 10倍〜20倍高速になる
• 電池消費の軽減
• Why faster?
• SIMD命令の有効利用
• 正確さとパフォーマンスのトレードオフ
特徴4 高速な新コンパイラ
Let’s read C# Job System codes!
• IJob~でジョブを定義
• Execute にジョブの中身を書く
• Schedule でジョブを開始
• Complete でジョブ終了確認
• 変数はNativeArray系を使い、自力でDispose
コーディング基本まとめ
• IJob
• 1つのスレッドでジョブを回す
• IJobParallelFor
• 複数のスレッドでジョブを回す
• IJobParallelForTransform
• Transformにアクセスが可能
コーディング基本まとめ
public void Execute() {}
public void Execute(int i) {}
public void Execute(int i, TransformAccess transform){}
Let’s make a mistake!
• マルチスレッドプログラミングは間違えやすい
• ちょっとした見落としはしてしまう
• Unityは落ちることなくエラーが教えてくれる
• CTO Joachim「Unityは「Sandbox(=砂場)」である」
• 砂場では間違っていい。正解に導いてくれれれば。
エラーまとめ
Let’s try “C# Job コンパイラ”
• 一文付け足すだけ
• [ComputeJobOptimizationAttribute(Accuracy
.Med, Support.Relaxed)]
• Accuracy は計算の精度
• 新しいmathライブラリ
C# Job Compiler
• float1, float2, float3, float4,
• half1, half2, half3, half4
• int1, int2, int3, int4
• math.abs
• math.min
• math.max
• math.pow
• math.lerp
• math.clamp
• math.saturate
• math.select // 条件分岐
• math.rcp // 逆数
• math.sign
• math.rsqrt // sqrtの逆数
• math.any
• math.all
• math.sincos
新mathライブラリ
Let’s implement C# Job System.
public class RotatorOldUpdate : MonoBehaviour
{
[SerializeField]
float m_Speed;
public float speed
{
get { return m_Speed; }
set { m_Speed = value; }
}
void Update ()
{
transform.rotation = transform.rotation * Quaternion.AngleAxis (m_Speed *
Time.deltaTime, Vector3.up);
}
}
• STEP1:データレイアウトの最適化
• GameObjectごとにするのはやめる
• データをシーケンシャルにする
• キャッシュ化する
• forループでGetComponentとかしなくてよくなる
Job Component System実装まとめ
public class RotatorOldUpdate : MonoBehaviour
{
[SerializeField]
float m_Speed;
public float speed
{
get { return m_Speed; }
set { m_Speed = value; }
}
void Update ()
{
transform.rotation = transform.rotation * Quaternion.AngleAxis (m_Speed *
Time.deltaTime, Vector3.up);
}
}
class RotatorManagerMainThread : ScriptBehaviourManager
{
List<Transform> m_Transforms;
NativeList<float> m_Speeds;
:
protected override void OnUpdate()
{
base.OnUpdate ();
float deltaTime = Time.deltaTime;
NativeArray<float> speeds = m_Speeds;
for (int i = 0; i != m_Transforms.Count; i++)
{
var transform = m_Transforms [i];
transform.rotation = transform.rotation * Quaternion.AngleAxis (speeds[i] * deltaTime, Vector3.up);
}
}
:
:
}
public class RotatorWithManagerMainThread : ScriptBehaviour
{
:
(たくさんの実装)
:
}
• STEP2: Job化
• List<Transform> → TransformAccessArray
• IJobParallelForTransform継承したジョブ
• Execute(int index, TransformAccess
transform)の実装
Job Component System実装まとめ
class RotatorManagerMainThread : ScriptBehaviourManager
{
List<Transform> m_Transforms;
NativeList<float> m_Speeds;
:
protected override void OnUpdate()
{
base.OnUpdate ();
float deltaTime = Time.deltaTime;
NativeArray<float> speeds = m_Speeds;
for (int i = 0; i != m_Transforms.Count; i++)
{
var transform = m_Transforms [i];
transform.rotation = transform.rotation * Quaternion.AngleAxis (speeds[i] * deltaTime, Vector3.up);
}
}
:
:
}
public class RotatorWithManagerMainThread : ScriptBehaviour
{
:
(たくさんの実装)
:
}
class RotatorManager : ScriptBehaviourManager
{
TransformAccessArray m_Transforms;
NativeList<float> m_Speeds;
JobHandle m_Job;
:
protected override void OnUpdate()
{
base.OnUpdate ();
m_Job.Complete ();
var jobData = new RotatorJob();
jobData.speeds = m_Speeds;
jobData.deltaTime = Time.deltaTime;
m_Job = jobData.Schedule (m_Transforms);
}
struct RotatorJob : IJobParallelForTransform
{
[ReadOnly]
public NativeArray<float> speeds;
public float deltaTime;
public void Execute(int index, TransformAccess transform)
{
transform.rotation = transform.rotation * Quaternion.AngleAxis (speeds[index] * deltaTime, Vector3.up);
}
}
}
public class RotatorWithManager : ScriptBehaviour
{
:
(たくさんの実装)
:
}
• STEP3: データからビヘイビアを分離する
• ジョブで使用するデータを分離する
• InjectTuplesの導入
• Tuples が付加した配列はindexが同期する
• ComponentSystemから継承させる
• マネージャーの仕事を任せる
Job Component System実装まとめ
public class RotationSpeedComponent : ScriptBehaviour
{
public float speed;
}
public class RotatingSystem : ComponentSystem
{
[InjectTuples]
public ComponentArray<Transform> m_Transforms;
[InjectTuples]
public ComponentArray<RotationSpeedComponent> m_Rotators;
override protected void OnUpdate()
{
base.OnUpdate ();
float dt = Time.deltaTime;
for (int i = 0; i != m_Transforms.Length ;i++)
{
m_Transforms[i].rotation =
m_Transforms[i].rotation * Quaternion.AngleAxis(dt * m_Rotators[i].speed, Vector3.up);
}
}
}
• STEP4: データのstruct化
• MonoBehaviour継承 → IComponentData継承
• struct化
• ComponentSystemからの継承でお手軽マネー
ジャー
• ComponentArray → ComponentDataArray
Job Component System実装まとめ
public class RotationSpeedComponent : ScriptBehaviour
{
public float speed;
}
public class RotatingSystem : ComponentSystem
{
[InjectTuples]
public ComponentArray<Transform> m_Transforms;
[InjectTuples]
public ComponentArray<RotationSpeedComponent> m_Rotators;
override protected void OnUpdate()
{
base.OnUpdate ();
float dt = Time.deltaTime;
for (int i = 0; i != m_Transforms.Length ;i++)
{
m_Transforms[i].rotation =
m_Transforms[i].rotation * Quaternion.AngleAxis(dt * m_Rotators[i].speed, Vector3.up);
}
}
}
[Serializable]
public struct RotationSpeed : IComponentData
{
public float speed;
public RotationSpeed (float speed) { this.speed = speed; }
}
public class RotationSpeedDataComponent : ComponentDataWrapper<RotationSpeed> { }
public class RotatingDataSystem : ComponentSystem
{
[InjectTuples]
public ComponentArray<Transform> m_Transforms;
[InjectTuples]
public ComponentDataArray<RotationSpeed> m_Rotators;
override protected void OnUpdate()
{
base.OnUpdate ();
float dt = Time.deltaTime;
for (int i = 0; i != m_Transforms.Length ;i++)
{
m_Transforms[i].rotation =
m_Transforms[i].rotation * Quaternion.AngleAxis(dt * m_Rotators[i].speed, Vector3.up);
}
}
}
• STEP5: ジョブ実装 と 依存性解決
• IJobParallelForTransformを継承したstruct
• Execute で Transformが使える
• ComponentSystem → JobComponentSystem
• GetDependency()で依存性の自動解決
Job Component System実装まとめ
[Serializable]
public struct RotationSpeed : IComponentData
{
public float speed;
public RotationSpeed (float speed) { this.speed = speed; }
}
public class RotationSpeedDataComponent : ComponentDataWrapper<RotationSpeed> { }
public class RotatingDataSystem : ComponentSystem
{
[InjectTuples]
public ComponentArray<Transform> m_Transforms;
[InjectTuples]
public ComponentDataArray<RotationSpeed> m_Rotators;
override protected void OnUpdate()
{
base.OnUpdate ();
float dt = Time.deltaTime;
for (int i = 0; i != m_Transforms.Length ;i++)
{
m_Transforms[i].rotation =
m_Transforms[i].rotation * Quaternion.AngleAxis(dt * m_Rotators[i].speed, Vector3.up);
}
}
}
[Serializable]
public struct RotationSpeed : IComponentData
{
public float speed;
public RotationSpeed (float speed) { this.speed = speed; }
}
public class RotationSpeedDataComponent : ComponentDataWrapper<RotationSpeed> { }
public class SystemRotator : JobComponentSystem
{
[InjectTuples]
public TransformAccessArray m_Transforms;
[InjectTuples]
public ComponentDataArray<RotationSpeed> m_Rotators;
override protected void OnUpdate()
{
base.OnUpdate ();
var job = new Job();
job.dt = Time.deltaTime;
job.rotators = m_Rotators;
AddDependency(job.Schedule(m_Transforms, GetDependency ()));
}
struct Job : IJobParallelForTransform
{
public float dt;
[ReadOnly]
public ComponentDataArray<RotationSpeed> rotators;
public void Execute(int i, TransformAccess transform)
{
transform.rotation =
transform.rotation * Quaternion.AngleAxis(dt * rotators[i].speed, Vector3.up);
}
}
}
C# Job System 注意点 & まとめ
• データ構造はstructのみ (class はNG)
• .NETやUnity のAPIはジョブ内では(基本的に)使えない
• 何でもかんでも早くなるわけではない
• 算術系が早くなる、と考えるのが正解
• 相互の距離の計算とか
• 敵AIの思考ルーチンとか
C# Job System 注意点
• STEP1 C# Job system
• Unity 2017.3 or 2018.X
• STEP2 Component system
• STEP3 math library
• STEP4 C# Job Compiler
リリース予定
• 多数の敵・味方が出るゲームでの相互距離の計算
• それによるソート
• RTS等で使う影響マップの生成
• 弾幕シューティング
• etc…
実際に何に使える?
• マルチスレッドプログラミングが安全に書ける
• 新しいComponent System で簡潔に書ける
• コンパイラをかければさらに早くなる
C# Job System まとめ
Q&A

More Related Content

More from Unity Technologies Japan K.K.

ビジュアルスクリプティング (旧:Bolt) で始めるUnity入門3日目 ゲームをカスタマイズしよう
ビジュアルスクリプティング (旧:Bolt) で始めるUnity入門3日目 ゲームをカスタマイズしようビジュアルスクリプティング (旧:Bolt) で始めるUnity入門3日目 ゲームをカスタマイズしよう
ビジュアルスクリプティング (旧:Bolt) で始めるUnity入門3日目 ゲームをカスタマイズしようUnity Technologies Japan K.K.
 
ビジュアルスクリプティングで始めるUnity入門2日目 ゴールとスコアの仕組み - Unityステーション
ビジュアルスクリプティングで始めるUnity入門2日目 ゴールとスコアの仕組み - Unityステーションビジュアルスクリプティングで始めるUnity入門2日目 ゴールとスコアの仕組み - Unityステーション
ビジュアルスクリプティングで始めるUnity入門2日目 ゴールとスコアの仕組み - UnityステーションUnity Technologies Japan K.K.
 
ビジュアルスクリプティングで始めるUnity入門1日目 プレイヤーを動かそう
ビジュアルスクリプティングで始めるUnity入門1日目 プレイヤーを動かそうビジュアルスクリプティングで始めるUnity入門1日目 プレイヤーを動かそう
ビジュアルスクリプティングで始めるUnity入門1日目 プレイヤーを動かそうUnity Technologies Japan K.K.
 
PlasticSCMの活用テクニックをハンズオンで一緒に学ぼう!
PlasticSCMの活用テクニックをハンズオンで一緒に学ぼう!PlasticSCMの活用テクニックをハンズオンで一緒に学ぼう!
PlasticSCMの活用テクニックをハンズオンで一緒に学ぼう!Unity Technologies Japan K.K.
 
点群を使いこなせ! 可視化なんて当たり前、xRと点群を組み合わせたUnityの世界 【Interact , Stipple】
点群を使いこなせ! 可視化なんて当たり前、xRと点群を組み合わせたUnityの世界 【Interact , Stipple】点群を使いこなせ! 可視化なんて当たり前、xRと点群を組み合わせたUnityの世界 【Interact , Stipple】
点群を使いこなせ! 可視化なんて当たり前、xRと点群を組み合わせたUnityの世界 【Interact , Stipple】Unity Technologies Japan K.K.
 
Unity教える先生方注目!ティーチャートレーニングデイを体験しよう
Unity教える先生方注目!ティーチャートレーニングデイを体験しようUnity教える先生方注目!ティーチャートレーニングデイを体験しよう
Unity教える先生方注目!ティーチャートレーニングデイを体験しようUnity Technologies Japan K.K.
 
「原神」におけるコンソールプラットフォーム開発
「原神」におけるコンソールプラットフォーム開発「原神」におけるコンソールプラットフォーム開発
「原神」におけるコンソールプラットフォーム開発Unity Technologies Japan K.K.
 
FANTASIANの明日使えない特殊テクニック教えます
FANTASIANの明日使えない特殊テクニック教えますFANTASIANの明日使えない特殊テクニック教えます
FANTASIANの明日使えない特殊テクニック教えますUnity Technologies Japan K.K.
 
インディーゲーム開発の現状と未来 2021
インディーゲーム開発の現状と未来 2021インディーゲーム開発の現状と未来 2021
インディーゲーム開発の現状と未来 2021Unity Technologies Japan K.K.
 
建築革命、更に進化!デジタルツイン基盤の真打ち登場【概要編 Unity Reflect ver 2.1 】
建築革命、更に進化!デジタルツイン基盤の真打ち登場【概要編 Unity Reflect ver 2.1 】建築革命、更に進化!デジタルツイン基盤の真打ち登場【概要編 Unity Reflect ver 2.1 】
建築革命、更に進化!デジタルツイン基盤の真打ち登場【概要編 Unity Reflect ver 2.1 】Unity Technologies Japan K.K.
 
Burstを使ってSHA-256のハッシュ計算を高速に行う話
Burstを使ってSHA-256のハッシュ計算を高速に行う話Burstを使ってSHA-256のハッシュ計算を高速に行う話
Burstを使ってSHA-256のハッシュ計算を高速に行う話Unity Technologies Japan K.K.
 
Cinemachineで見下ろし視点のカメラを作る
Cinemachineで見下ろし視点のカメラを作るCinemachineで見下ろし視点のカメラを作る
Cinemachineで見下ろし視点のカメラを作るUnity Technologies Japan K.K.
 
Unityティーチャートレーニングデイ -認定プログラマー編-
Unityティーチャートレーニングデイ -認定プログラマー編-Unityティーチャートレーニングデイ -認定プログラマー編-
Unityティーチャートレーニングデイ -認定プログラマー編-Unity Technologies Japan K.K.
 
Unityティーチャートレーニングデイ -認定3Dアーティスト編-
Unityティーチャートレーニングデイ -認定3Dアーティスト編-Unityティーチャートレーニングデイ -認定3Dアーティスト編-
Unityティーチャートレーニングデイ -認定3Dアーティスト編-Unity Technologies Japan K.K.
 
Unityティーチャートレーニングデイ -認定アソシエイト編-
Unityティーチャートレーニングデイ -認定アソシエイト編-Unityティーチャートレーニングデイ -認定アソシエイト編-
Unityティーチャートレーニングデイ -認定アソシエイト編-Unity Technologies Japan K.K.
 
今だから聞きたい!Unity2017/18ユーザーのためのUnity2019 LTS基礎知識
今だから聞きたい!Unity2017/18ユーザーのためのUnity2019 LTS基礎知識 今だから聞きたい!Unity2017/18ユーザーのためのUnity2019 LTS基礎知識
今だから聞きたい!Unity2017/18ユーザーのためのUnity2019 LTS基礎知識 Unity Technologies Japan K.K.
 
【Unity Reflect】無料のViewerに機能が増えた!?~お披露目会編~
【Unity Reflect】無料のViewerに機能が増えた!?~お披露目会編~【Unity Reflect】無料のViewerに機能が増えた!?~お披露目会編~
【Unity Reflect】無料のViewerに機能が増えた!?~お披露目会編~Unity Technologies Japan K.K.
 
ビジュアルスクリプティングシステムBoltを使ってみよう 2回目
ビジュアルスクリプティングシステムBoltを使ってみよう 2回目ビジュアルスクリプティングシステムBoltを使ってみよう 2回目
ビジュアルスクリプティングシステムBoltを使ってみよう 2回目Unity Technologies Japan K.K.
 

More from Unity Technologies Japan K.K. (20)

ビジュアルスクリプティング (旧:Bolt) で始めるUnity入門3日目 ゲームをカスタマイズしよう
ビジュアルスクリプティング (旧:Bolt) で始めるUnity入門3日目 ゲームをカスタマイズしようビジュアルスクリプティング (旧:Bolt) で始めるUnity入門3日目 ゲームをカスタマイズしよう
ビジュアルスクリプティング (旧:Bolt) で始めるUnity入門3日目 ゲームをカスタマイズしよう
 
ビジュアルスクリプティングで始めるUnity入門2日目 ゴールとスコアの仕組み - Unityステーション
ビジュアルスクリプティングで始めるUnity入門2日目 ゴールとスコアの仕組み - Unityステーションビジュアルスクリプティングで始めるUnity入門2日目 ゴールとスコアの仕組み - Unityステーション
ビジュアルスクリプティングで始めるUnity入門2日目 ゴールとスコアの仕組み - Unityステーション
 
ビジュアルスクリプティングで始めるUnity入門1日目 プレイヤーを動かそう
ビジュアルスクリプティングで始めるUnity入門1日目 プレイヤーを動かそうビジュアルスクリプティングで始めるUnity入門1日目 プレイヤーを動かそう
ビジュアルスクリプティングで始めるUnity入門1日目 プレイヤーを動かそう
 
PlasticSCMの活用テクニックをハンズオンで一緒に学ぼう!
PlasticSCMの活用テクニックをハンズオンで一緒に学ぼう!PlasticSCMの活用テクニックをハンズオンで一緒に学ぼう!
PlasticSCMの活用テクニックをハンズオンで一緒に学ぼう!
 
点群を使いこなせ! 可視化なんて当たり前、xRと点群を組み合わせたUnityの世界 【Interact , Stipple】
点群を使いこなせ! 可視化なんて当たり前、xRと点群を組み合わせたUnityの世界 【Interact , Stipple】点群を使いこなせ! 可視化なんて当たり前、xRと点群を組み合わせたUnityの世界 【Interact , Stipple】
点群を使いこなせ! 可視化なんて当たり前、xRと点群を組み合わせたUnityの世界 【Interact , Stipple】
 
Unity教える先生方注目!ティーチャートレーニングデイを体験しよう
Unity教える先生方注目!ティーチャートレーニングデイを体験しようUnity教える先生方注目!ティーチャートレーニングデイを体験しよう
Unity教える先生方注目!ティーチャートレーニングデイを体験しよう
 
「原神」におけるコンソールプラットフォーム開発
「原神」におけるコンソールプラットフォーム開発「原神」におけるコンソールプラットフォーム開発
「原神」におけるコンソールプラットフォーム開発
 
FANTASIANの明日使えない特殊テクニック教えます
FANTASIANの明日使えない特殊テクニック教えますFANTASIANの明日使えない特殊テクニック教えます
FANTASIANの明日使えない特殊テクニック教えます
 
インディーゲーム開発の現状と未来 2021
インディーゲーム開発の現状と未来 2021インディーゲーム開発の現状と未来 2021
インディーゲーム開発の現状と未来 2021
 
建築革命、更に進化!デジタルツイン基盤の真打ち登場【概要編 Unity Reflect ver 2.1 】
建築革命、更に進化!デジタルツイン基盤の真打ち登場【概要編 Unity Reflect ver 2.1 】建築革命、更に進化!デジタルツイン基盤の真打ち登場【概要編 Unity Reflect ver 2.1 】
建築革命、更に進化!デジタルツイン基盤の真打ち登場【概要編 Unity Reflect ver 2.1 】
 
Burstを使ってSHA-256のハッシュ計算を高速に行う話
Burstを使ってSHA-256のハッシュ計算を高速に行う話Burstを使ってSHA-256のハッシュ計算を高速に行う話
Burstを使ってSHA-256のハッシュ計算を高速に行う話
 
Cinemachineで見下ろし視点のカメラを作る
Cinemachineで見下ろし視点のカメラを作るCinemachineで見下ろし視点のカメラを作る
Cinemachineで見下ろし視点のカメラを作る
 
徹底解説 Unity Reflect【開発編 ver2.0】
徹底解説 Unity Reflect【開発編 ver2.0】徹底解説 Unity Reflect【開発編 ver2.0】
徹底解説 Unity Reflect【開発編 ver2.0】
 
徹底解説 Unity Reflect【概要編 ver2.0】
徹底解説 Unity Reflect【概要編 ver2.0】徹底解説 Unity Reflect【概要編 ver2.0】
徹底解説 Unity Reflect【概要編 ver2.0】
 
Unityティーチャートレーニングデイ -認定プログラマー編-
Unityティーチャートレーニングデイ -認定プログラマー編-Unityティーチャートレーニングデイ -認定プログラマー編-
Unityティーチャートレーニングデイ -認定プログラマー編-
 
Unityティーチャートレーニングデイ -認定3Dアーティスト編-
Unityティーチャートレーニングデイ -認定3Dアーティスト編-Unityティーチャートレーニングデイ -認定3Dアーティスト編-
Unityティーチャートレーニングデイ -認定3Dアーティスト編-
 
Unityティーチャートレーニングデイ -認定アソシエイト編-
Unityティーチャートレーニングデイ -認定アソシエイト編-Unityティーチャートレーニングデイ -認定アソシエイト編-
Unityティーチャートレーニングデイ -認定アソシエイト編-
 
今だから聞きたい!Unity2017/18ユーザーのためのUnity2019 LTS基礎知識
今だから聞きたい!Unity2017/18ユーザーのためのUnity2019 LTS基礎知識 今だから聞きたい!Unity2017/18ユーザーのためのUnity2019 LTS基礎知識
今だから聞きたい!Unity2017/18ユーザーのためのUnity2019 LTS基礎知識
 
【Unity Reflect】無料のViewerに機能が増えた!?~お披露目会編~
【Unity Reflect】無料のViewerに機能が増えた!?~お披露目会編~【Unity Reflect】無料のViewerに機能が増えた!?~お披露目会編~
【Unity Reflect】無料のViewerに機能が増えた!?~お披露目会編~
 
ビジュアルスクリプティングシステムBoltを使ってみよう 2回目
ビジュアルスクリプティングシステムBoltを使ってみよう 2回目ビジュアルスクリプティングシステムBoltを使ってみよう 2回目
ビジュアルスクリプティングシステムBoltを使ってみよう 2回目
 

Recently uploaded

論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNetToru Tamaki
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものですiPride Co., Ltd.
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...Toru Tamaki
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdftaisei2219
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A surveyToru Tamaki
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)Hiroki Ichikura
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Yuma Ohgami
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 

Recently uploaded (9)

論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdf
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 

【CEDEC2017】C#JobSystem を使った Unity流マルチスレッドプログラミング

  • 2. • 今回紹介するC# Job Systemはまだ発展段階 • リリースでは多少の差異が出る可能性がある • C# Job Systemの概念を知ってほしい • プログラマ以外は理解不能 諸注意
  • 3. • 従来のマルチスレッドプログラミング • C# Job System の概要 • Let’s read codes. (コードを読む) • Let’s make a mistake. (間違ってみる) • Let’s try “C# Job Compiler” (コンパイラを体験) • Let’s implement. (実装してみる) • まとめ アジェンダ
  • 7. • レースコンディション対策が嫌だ • 面倒臭い • コードが汚い、可読性が低い • 間違っても気づきにくい MTPのここが嫌だ その1 Aが使うよ Aが使うよ Bが使うよ A AB ? write write read
  • 8. • デッドロックが嫌だ • 面倒臭い • コードが汚い、可読性が低い • 間違うと無限ループ MTPのここが嫌だ その2 A AB B 待ち待ち
  • 9. • 難解なところが嫌だ • mutex:lockとか • アトミック変数とか MTPのここが嫌だ その3
  • 10. • デバッグが嫌だ • 正常に”動いてしまったり”する • 無限ループになったりする • 突然ハングアップしたりする • リリース後にバグが判明したりする MTPのここが嫌だ その4
  • 13. C# Job System の概要
  • 15. 116
  • 16.
  • 17.
  • 18. 116倍Boid シミュレーションを マルチスレッドで 8 core CPUで 動かした場合の速度倍
  • 19. Demo
  • 20. • 簡潔に書ける • GCフリー • 安全 • 高速な新コンパイラ C# Job System の特徴
  • 21. • Data Oriented Programming • データとビヘイビア(振舞い)の分離 • struct(構造体)コンポーネントの導入 • Job Component System の用意 • 簡潔に書けるようにマネージャーを用意 特徴1 簡潔に書ける
  • 22. • GCをいかにさせないか • NativeArrayの導入      • 以下の感じで確保 • 以下の感じで解放(自分で) 特徴2 GCフリー var src = new NativeArray<float>(500, Allocator.Temp); src.Dispose();  要素数 アロケーターの種類   ↓     ↓
  • 23. • 他のNativeArrayファミリー 特徴2 GCフリー struct NativeArray<Value> // 配列 struct NativeList<Value> // リスト。追加削除が容易 struct NativeSlice<Value> // 一部を切り取れる struct NativeHashmap<Key, Value> // Dictionary「 struct NativeMultiHashmap<Key, Value> //複数Dictionary
  • 24. • エラーで指摘してくれる • 落ちることはない • レースコンディション、デッドロックは起こり得ない • “Sandbox” 特徴3 安全
  • 25. • C#→[Mono]→IL→[C# Job Compiler]→内部的な Domain Model →[最適化]→[LLVM]→実行形式 • 10倍〜20倍高速になる • 電池消費の軽減 • Why faster? • SIMD命令の有効利用 • 正確さとパフォーマンスのトレードオフ 特徴4 高速な新コンパイラ
  • 26. Let’s read C# Job System codes!
  • 27. • IJob~でジョブを定義 • Execute にジョブの中身を書く • Schedule でジョブを開始 • Complete でジョブ終了確認 • 変数はNativeArray系を使い、自力でDispose コーディング基本まとめ
  • 28. • IJob • 1つのスレッドでジョブを回す • IJobParallelFor • 複数のスレッドでジョブを回す • IJobParallelForTransform • Transformにアクセスが可能 コーディング基本まとめ public void Execute() {} public void Execute(int i) {} public void Execute(int i, TransformAccess transform){}
  • 29. Let’s make a mistake!
  • 30. • マルチスレッドプログラミングは間違えやすい • ちょっとした見落としはしてしまう • Unityは落ちることなくエラーが教えてくれる • CTO Joachim「Unityは「Sandbox(=砂場)」である」 • 砂場では間違っていい。正解に導いてくれれれば。 エラーまとめ
  • 31. Let’s try “C# Job コンパイラ”
  • 32. • 一文付け足すだけ • [ComputeJobOptimizationAttribute(Accuracy .Med, Support.Relaxed)] • Accuracy は計算の精度 • 新しいmathライブラリ C# Job Compiler
  • 33. • float1, float2, float3, float4, • half1, half2, half3, half4 • int1, int2, int3, int4 • math.abs • math.min • math.max • math.pow • math.lerp • math.clamp • math.saturate • math.select // 条件分岐 • math.rcp // 逆数 • math.sign • math.rsqrt // sqrtの逆数 • math.any • math.all • math.sincos 新mathライブラリ
  • 34. Let’s implement C# Job System.
  • 35. public class RotatorOldUpdate : MonoBehaviour { [SerializeField] float m_Speed; public float speed { get { return m_Speed; } set { m_Speed = value; } } void Update () { transform.rotation = transform.rotation * Quaternion.AngleAxis (m_Speed * Time.deltaTime, Vector3.up); } }
  • 36. • STEP1:データレイアウトの最適化 • GameObjectごとにするのはやめる • データをシーケンシャルにする • キャッシュ化する • forループでGetComponentとかしなくてよくなる Job Component System実装まとめ
  • 37. public class RotatorOldUpdate : MonoBehaviour { [SerializeField] float m_Speed; public float speed { get { return m_Speed; } set { m_Speed = value; } } void Update () { transform.rotation = transform.rotation * Quaternion.AngleAxis (m_Speed * Time.deltaTime, Vector3.up); } }
  • 38. class RotatorManagerMainThread : ScriptBehaviourManager { List<Transform> m_Transforms; NativeList<float> m_Speeds; : protected override void OnUpdate() { base.OnUpdate (); float deltaTime = Time.deltaTime; NativeArray<float> speeds = m_Speeds; for (int i = 0; i != m_Transforms.Count; i++) { var transform = m_Transforms [i]; transform.rotation = transform.rotation * Quaternion.AngleAxis (speeds[i] * deltaTime, Vector3.up); } } : : } public class RotatorWithManagerMainThread : ScriptBehaviour { : (たくさんの実装) : }
  • 39. • STEP2: Job化 • List<Transform> → TransformAccessArray • IJobParallelForTransform継承したジョブ • Execute(int index, TransformAccess transform)の実装 Job Component System実装まとめ
  • 40. class RotatorManagerMainThread : ScriptBehaviourManager { List<Transform> m_Transforms; NativeList<float> m_Speeds; : protected override void OnUpdate() { base.OnUpdate (); float deltaTime = Time.deltaTime; NativeArray<float> speeds = m_Speeds; for (int i = 0; i != m_Transforms.Count; i++) { var transform = m_Transforms [i]; transform.rotation = transform.rotation * Quaternion.AngleAxis (speeds[i] * deltaTime, Vector3.up); } } : : } public class RotatorWithManagerMainThread : ScriptBehaviour { : (たくさんの実装) : }
  • 41. class RotatorManager : ScriptBehaviourManager { TransformAccessArray m_Transforms; NativeList<float> m_Speeds; JobHandle m_Job; : protected override void OnUpdate() { base.OnUpdate (); m_Job.Complete (); var jobData = new RotatorJob(); jobData.speeds = m_Speeds; jobData.deltaTime = Time.deltaTime; m_Job = jobData.Schedule (m_Transforms); } struct RotatorJob : IJobParallelForTransform { [ReadOnly] public NativeArray<float> speeds; public float deltaTime; public void Execute(int index, TransformAccess transform) { transform.rotation = transform.rotation * Quaternion.AngleAxis (speeds[index] * deltaTime, Vector3.up); } } } public class RotatorWithManager : ScriptBehaviour { : (たくさんの実装) : }
  • 42. • STEP3: データからビヘイビアを分離する • ジョブで使用するデータを分離する • InjectTuplesの導入 • Tuples が付加した配列はindexが同期する • ComponentSystemから継承させる • マネージャーの仕事を任せる Job Component System実装まとめ
  • 43. public class RotationSpeedComponent : ScriptBehaviour { public float speed; } public class RotatingSystem : ComponentSystem { [InjectTuples] public ComponentArray<Transform> m_Transforms; [InjectTuples] public ComponentArray<RotationSpeedComponent> m_Rotators; override protected void OnUpdate() { base.OnUpdate (); float dt = Time.deltaTime; for (int i = 0; i != m_Transforms.Length ;i++) { m_Transforms[i].rotation = m_Transforms[i].rotation * Quaternion.AngleAxis(dt * m_Rotators[i].speed, Vector3.up); } } }
  • 44. • STEP4: データのstruct化 • MonoBehaviour継承 → IComponentData継承 • struct化 • ComponentSystemからの継承でお手軽マネー ジャー • ComponentArray → ComponentDataArray Job Component System実装まとめ
  • 45. public class RotationSpeedComponent : ScriptBehaviour { public float speed; } public class RotatingSystem : ComponentSystem { [InjectTuples] public ComponentArray<Transform> m_Transforms; [InjectTuples] public ComponentArray<RotationSpeedComponent> m_Rotators; override protected void OnUpdate() { base.OnUpdate (); float dt = Time.deltaTime; for (int i = 0; i != m_Transforms.Length ;i++) { m_Transforms[i].rotation = m_Transforms[i].rotation * Quaternion.AngleAxis(dt * m_Rotators[i].speed, Vector3.up); } } }
  • 46. [Serializable] public struct RotationSpeed : IComponentData { public float speed; public RotationSpeed (float speed) { this.speed = speed; } } public class RotationSpeedDataComponent : ComponentDataWrapper<RotationSpeed> { } public class RotatingDataSystem : ComponentSystem { [InjectTuples] public ComponentArray<Transform> m_Transforms; [InjectTuples] public ComponentDataArray<RotationSpeed> m_Rotators; override protected void OnUpdate() { base.OnUpdate (); float dt = Time.deltaTime; for (int i = 0; i != m_Transforms.Length ;i++) { m_Transforms[i].rotation = m_Transforms[i].rotation * Quaternion.AngleAxis(dt * m_Rotators[i].speed, Vector3.up); } } }
  • 47. • STEP5: ジョブ実装 と 依存性解決 • IJobParallelForTransformを継承したstruct • Execute で Transformが使える • ComponentSystem → JobComponentSystem • GetDependency()で依存性の自動解決 Job Component System実装まとめ
  • 48. [Serializable] public struct RotationSpeed : IComponentData { public float speed; public RotationSpeed (float speed) { this.speed = speed; } } public class RotationSpeedDataComponent : ComponentDataWrapper<RotationSpeed> { } public class RotatingDataSystem : ComponentSystem { [InjectTuples] public ComponentArray<Transform> m_Transforms; [InjectTuples] public ComponentDataArray<RotationSpeed> m_Rotators; override protected void OnUpdate() { base.OnUpdate (); float dt = Time.deltaTime; for (int i = 0; i != m_Transforms.Length ;i++) { m_Transforms[i].rotation = m_Transforms[i].rotation * Quaternion.AngleAxis(dt * m_Rotators[i].speed, Vector3.up); } } }
  • 49. [Serializable] public struct RotationSpeed : IComponentData { public float speed; public RotationSpeed (float speed) { this.speed = speed; } } public class RotationSpeedDataComponent : ComponentDataWrapper<RotationSpeed> { } public class SystemRotator : JobComponentSystem { [InjectTuples] public TransformAccessArray m_Transforms; [InjectTuples] public ComponentDataArray<RotationSpeed> m_Rotators; override protected void OnUpdate() { base.OnUpdate (); var job = new Job(); job.dt = Time.deltaTime; job.rotators = m_Rotators; AddDependency(job.Schedule(m_Transforms, GetDependency ())); } struct Job : IJobParallelForTransform { public float dt; [ReadOnly] public ComponentDataArray<RotationSpeed> rotators; public void Execute(int i, TransformAccess transform) { transform.rotation = transform.rotation * Quaternion.AngleAxis(dt * rotators[i].speed, Vector3.up); } } }
  • 50. C# Job System 注意点 & まとめ
  • 51. • データ構造はstructのみ (class はNG) • .NETやUnity のAPIはジョブ内では(基本的に)使えない • 何でもかんでも早くなるわけではない • 算術系が早くなる、と考えるのが正解 • 相互の距離の計算とか • 敵AIの思考ルーチンとか C# Job System 注意点
  • 52. • STEP1 C# Job system • Unity 2017.3 or 2018.X • STEP2 Component system • STEP3 math library • STEP4 C# Job Compiler リリース予定
  • 53. • 多数の敵・味方が出るゲームでの相互距離の計算 • それによるソート • RTS等で使う影響マップの生成 • 弾幕シューティング • etc… 実際に何に使える?
  • 54. • マルチスレッドプログラミングが安全に書ける • 新しいComponent System で簡潔に書ける • コンパイラをかければさらに早くなる C# Job System まとめ
  • 55. Q&A