##変更履歴
- 英単語のつづりの間違いをいくつか修正(ご指摘いただいた方,ありがとうございました.)
- 性能の章にちょっとだけ,考察を追加
新しいリアルタイムスレッドライブラリとはなにか
librealtimeと言います.C++11で動作します.
ここにあります
APIの説明はこちら
本稿を読んで得られるもの
- そこそこ厳密な周期実行スレッドを作成するライブラリの使い方
- 優先度を付与されたスレッドを作成するライブラリの使い方
- そのライブラリの性能に関する知識
では,ご覧ください.
制御工学やロボットの分野では厳密なリアルタイム性が重要です.
このライブラリはそのような厳密なリアルタイム性をお手軽に手に入れようというものです.
有名ドコロではXENOMAIやRTAIが有名で,人工衛星などにも使用されているそうです.
日本製のライブラリだとARCSが有名だと思います.
しかし,このようなライブラリは性能は素晴らしいのですが,使う前の準備が大変であったり
必要な知識が山ほどあって,脳が発火すること間違いなしです.
そこで,そこそこの性能(1000 [Hz]くらい)をできるだけ簡単に使えるようにしようというのが
このライブラリのコンセプトであります.
すごく小さく全部合わせても200行も行かないと思われます.そうです.エコなんです.
リアルタイムとは
CPUは怠け者であり,効率厨でもあります.
たとえば,1秒間に10回だけ,0.1行刻みで,この関数を実行してよ とお願いしたとします.
そうすると科学の申し子であるCPUくんはこう答えるでしょう.
「ええよ,でも,今忙しいから,0.9秒後にまとめて関数を10回実行したるで!」
リアルタイムとは,このCPUくんに性格矯正ギブスを装着させて,
「了解いたしました.では0.1秒に1回だけ実行し,1秒後に10回分の実行が完了するようにします」
と答えさせるようにすることです.
この,性格が矯正されたCPUくんの持つ性質のことをリアルタイム性と呼びます.
つまり,決められた時間に必ず関数が実行されるという性能のことを言います.
librealtimeの説明
では,そんな感じで性格矯正ギブスをCPUに装着させるライブラリlibrealtimeの使い方の説明をしていきたいと思います.また,使用できる環境はLinuxのみであります.
インストール
ヘッダーオンリーなのでダウンロードしてきて,所定の場所にコピーするだけです.
以下の感じで行ってください.ハイ.
git clone https://github.com/harumo11/librealtime.git
cd librealtime
sudo cp -r librealtime /usr/local/include
さらにサンプルを実行する場合は
cd example
mkdir build
cd build
cmake ../
sudo ./testRealtimeThread
としてください.実行結果がlog.csvにできているはずです.
もっと簡単なサンプルをお望みの場合は,本稿のもうちょっと下にあるサンプルプログラムをご覧ください.
使い方
librealtimeには2つのクラスがあります.
1つはリアルタイム性能を付与したスレッドを作成するクラス
もうひとつはスレッドにプライオリティ(優先度)を付与するクラスです.
1. RealtimeThread
使い方はほとんどstd::threadと同じなのですが,下の例のように実行周期[Hz]をスレッドのコンストラクタに与えてあげてください.そして,良きところで,start()を読んでください.
そうすると,その周期で与えられた関数をRealtimeThreadクラス内部のwhileループでjoin()かdetach()が呼ばれるまで,実行し続けます.
start()の引数にtrueを与えるとリアルタイム性能を付加されたスレッドになります.
falseを与えた場合には,リアルタイムでない周期を持つスレッドになります.
start(true)とした場合には,スーパーユーザー権限でプログラムを実行してください.
#include <iostream>
#include <unistd.h>
#include <librealtime/RealtimeThread.hpp>
void func_real(int num){
std::cout << "This is Real-Time periodic thread " << num << std::endl;
}
int main(void){
//(Frequency[Hz], function, arguments)
RealtimeThread rth(10, func, 1234);
//Run in 3 sec. If set true, get RealTime thread, otherwise, nomal priodic thread.
rth.start(true);
sleep(3);
rth.join();
}
コンパイルにはC++11とpthreadをリンクするのも忘れないでください.
CMakeを使用する場合には,サンプルがexampleディレクトリの中に同梱してあります.
実行はスーパーユーザー権限が必要なので,こんな感じでお願いします.
sudo ./program
2. PolicyThread
普通のスレッドにプライオリティを付与したスレッドを作成する場合は
こちらのクラスを作成してください.
サンプルはこんな感じです.
#include <iostream>
#include <librealtime/PolicyThread.hpp>
void func_policy(int num){
std::cout << "This is Policy-Thread " << num << std::endl;
}
int main(void){
//set function and arguments
PolicyThread pth(func_policy, num);
//(Priority. from 0 to 99)
pth.start(30);
pth.join();
}
start()ではプライオリティを設定しています.0から99まで選択できます.
0がプライオリティが最小.つまり,ただのスレッドです.
99が最大で,他に動いているプログラムがあっても,それを押しのけて実行されます.
こちらも,C++11とpthreadのリンク,スーパーユーザー権限での実行を忘れないでください.
同様に,librealtime/exampleにプログラムとCMakeのサンプルが同梱されています.
実行するときは
sudo ./sample
としてください.
性能
RealtimeThreadとPolicyThreadって2つあるけど,
要はPolicyThreadにプライオリティ99を与えて,週期実行する関数を実行させたら,RealtimeThreadでしょ?!と考えた,そこのあなた!
そんなあなたのために実験しておきました.
このことに感謝感激雨あられしちゃった人はいいねを押してくださいね.
1秒間に1000回関数を実行させるようにして,それぞれのクラスでスレッドを作成したら
どうなっちゃうのでしょうか.
結果は以下の感じになりました.
Thread | Average | Standard deviation | Counts |
---|---|---|---|
RealtimeThread | 1000129.986[nano sec] | 1452.211[nano sec] | 1000/1000 times |
PolicyThread | 1060530.358[nano sec] | 12778.745[nano sec] | 944/1000 times |
なんと,PolicyThreadは944回しか関数を実行できませんでした.途中で怠けたのでしょうか.
このように怠けていると最終的に差が出るという教訓をこのライブラリを使用することで,
実感することもできます.
あと,なんだかばらつきもあります.
規則正しい生活が大事であることも,このライブラリは教えてくれます.
なぜ,このような違いが出るのかと言いますと,RealtimeThtreadとPolicyThreadでは
設定しているLinuxカーネルのスケジューリングポリシーが違うからでございます.
RealtimeThreadでは,SCHED_DEADLINEという周期実行向けのポリシーを設定しており,
PolicyThreadでは,SCHED_FIFOを設定するようにしています.
詳しくはこちらをご覧ください.
お待ち申し上げております.
えー,うさぎは寂しいと死んでしまうと言います.
本宅の猫は,寂しくても,決して自ら飼い主に近づこうとはせず,
飼い主を呼びつけます.
では,私はどうかと考えたところ,私もコメントをいただけないと寂しさで,夜中にラーメンをすすってしまい体重増加がマッハでございます.
私の体重のためにも,コメント,修正など,お待ち申し上げております.