[openrtm-users 01351] Re: high CPU load when deactivate python component
Ando Noriaki
n-ando @ aist.go.jp
2010年 7月 6日 (火) 22:59:51 JST
みなさま
安藤です
ほぼ栗原さんからの返答で言い尽くされていると思いますが少し補足を。
ECとRTCの関係ですが、PeriodicExecutionContext::svc() がまさに
その部分になるかと思います。
do
{
m_worker.mutex_.unlock();
while (!m_worker.running_)
{
m_worker.cond_.wait(); // stopped状態のときここで待つ
}
if (m_worker.running_)
{
std::for_each(m_comps.begin(), m_comps.end(),
invoke_worker()); // すべてのRTCのアクションを実行
}
m_worker.mutex_.unlock();
if (!m_nowait) { coil::sleep(m_period); }
} while (m_svc);
invoke_worker() の中身ですが、コンポーネントの現在の状態の
アクション (on_何とか) を実行するものだと思ってください。
なお、Inactive 状態は、on_何とかに相当する関数がないので
ダミーの空の関数が実行されていると思ってください。
do-while の for_each の部分を書き下すと、コンポーネントがそれぞれ以下の状態にある場合
RTC0: inactive
RTC1: active
RTC2: active
RTC3: error
do-while の for_each 内
RTC0. dummy();
RTC1: on_execute();
RTC2: on_execute'(;
RTC3: on_error();
ということになります。したがって、RTC0がinactive状態ですが、
ループを止めるわけにはいきません。
清水さんがおっしゃるように、すべてのRTCがinactiveの場合は
ループを止めてもいいのですが、そうなると、
#以下適当なコードですが、
do
{
m_worker.mutex_.lock();
while (!m_worker.running_)
{
m_worker.cond_.wait(); // ECのstopped状態のときにここで止まってる
}
if (m_worker.running_) // ECがrunning状態のとき
{
m_inactivewait.mutex_.lock();
inactivecomps = for_each(m_comps.begin(), m_comps.end(),
Inactivecomps()); // (1) Inactiveかどうか調べる
while (inactivecomps.num() == m_comps.size()) {
m_inactivewait.cond_.wait(); } // (2) 全部inactiveならwait
std::for_each(m_comps.begin(), m_comps.end(),
invoke_worker()); // (3) 各RTCのアクションを実行
m_inactivewait.mutex_.unlock();
}
m_worker.mutex_.unlock();
if (!m_nowait) { coil::sleep(m_period); }
} while (m_svc);
という感じで、毎周期すべてのコンポーネントを調べる必要があります。
#別の実装としては、ECのactivate_component() などの呼び出しから、
#現在アタッチされているRTCの状態がInactiveかどうかをEC自体が常に補足
#するという方法もありますかね?
この部分は、リアルタイム実行される可能性もあるので、これを
取り込むかどうかは (1) の for_each がどのくらいの時間がかかるかにもよると思います。
あと、ロックが追加されている部分と、ECのもうひとつの状態遷移(stopped<->running)
との兼ね合いについてもよく考える必要があります。(デッドロックが起こらないかどうかなど)
というわけですので、今後の検討課題とさせてください。
2010年7月6日19:15 kurihara shinji <shinji.kurihara @ aist.go.jp>:
> 松坂様
>
> 栗原です。
>
> 以下は、一つのExecutionContextに対して複数のRTCが登録された場合についてです。
>
>> ・ExecutionContextは直列リストの構造をしている。
> ExecutionContextは、add_component(rtobj)にて登録されたRTCをリストで管理してお
> り、whileループの中では、リストに登録されているRTCのアクティビティ処理を呼び出し
> ます。(正確には、StateMachineから呼ばれます。)
>
>> ・ただし、あくまで分散コンポーネントモデルなので中央でコンテキストを管理している
>> サービスがあるわけではなく、各コンポーネント同士がバケツリレーのような形で
>> 実行タイミングを通知しあっている。
> RTCのリストに登録してある順番でRTCのon_execute()などを呼びますので、たとえば、
> 3つのRTC(A,B,C)が登録されていて、3つのRTCがACTIVE状態であれば、Aのon_execute
> ()が戻ってきて、Bのon_execute(),Cのon_execute()のようになります。
> よって、各コンポーネント同士が実行タイミングを通知しあっているのではなく、
> あるRTCのアクティビティ処理が終了次第、次のRTCのアクティビティ処理の実行をECが
> 行うといった仕様になっております。
>
>
> 以上、宜しくお願い致します。
>
>
> On Tue, 6 Jul 2010 17:44:54 +0900
> Yosuke Matsusaka <yosuke.matsusaka @ aist.go.jp> wrote:
>
>> 栗原さん
>>
>> 松坂です。
>>
>> 2010/7/6 kurihara shinji <shinji.kurihara @ aist.go.jp>:
>> > RTMでは、一つのExecutionContextで複数のRTCを駆動する事が可能となっております。
>> > 仮に、非アクティブ状態でループを回さないようにした場合、一つのECに複数のRTC
>> > が関連付けられてる状況において、一つの RTC が非アクティブ状態の時に、他のアク
>> > ティブ状態のRTCまでも駆動関数(on_execute)が実行されないといった事になってしまい
>> > ます。
>> >
>> > 上記のような理由もあり、ExecutionContextのループは、RTCの状態に関わらずループ
>> > する仕様となっております。
>>
>> なるほど、理解しました。
>> 金広さん、清水さんの議論を読んで、何となく私の理解がずれている予感がしていたのですが、
>> これでクリアになりました。
>>
>> ・ExecutionContextは直列リストの構造をしている。
>> ・ただし、あくまで分散コンポーネントモデルなので中央でコンテキストを管理している
>> サービスがあるわけではなく、各コンポーネント同士がバケツリレーのような形で
>> 実行タイミングを通知しあっている。
>>
>> というわけですね。
>> 改良しようとしてもなかなか難しいところですね、、、。
>>
>> --
>> Yosuke Matsusaka, Ph.D <yosuke.matsusaka @ aist.go.jp>
>> Interaction Modeling Group /
>> National Institute of Advanced Industrial Science and Technology (AIST)
>> Tel: 029-862-6726 Web: http://staff.aist.go.jp/yosuke.matsusaka/
>>
>
>
> --
> ----------
> 栗原 眞二 <shinji.kurihara @ aist.go.jp>
>
> 独立行政法人産業技術総合研究所
> 知能システム研究部門 統合知能研究グループ
> 〒305-8568
> 茨城県つくば市梅園1-1-1 中央第2
>
> TEL: 029-861-5956
>
>
--
安藤慶昭@独立行政法人産業技術総合研究所 知能システム研究部門
統合知能研究グループ 主任研究員, 博士(工学)
〒305-8568 つくば市梅園1-1-1 中央第2
e-mail: n-ando @ aist.go.jp, web: http://staff.aist.go.jp/n-ando
OpenRTM-aist: http://www.openrtm.org
openrtm-users メーリングリストの案内