アプリ版:「スタンプのみでお礼する」機能のリリースについて

8~16bit、32bitのマイコンでCの組み込みプログラムを仕事で作りはじめました。
その中で、floatやdoubleといった実数型は使わないようにと教わりました。コードサイズが大きくなること、処理時間が大きくなることが理由だと考えていますが、定量的に考察したことがありません。
そこで、コンパイラのhelpを検索してみたところANSI-Cで決められているほど広くないにしても使えることが書いてありました。しかしながら、先輩たちはその使用をかたくなに拒みます。しかし、理由も先ほどのような感じです。
もし仮に、コードサイズや処理時間に問題ないとしても実数型を使わない理由を教えていただけませんでしょうか?

A 回答 (12件中1~10件)

ルネサスのH8マイコンで、int同士の掛け算、割り算と double同士の掛け算、割り算でどれくらい処理速度に差が出るか定量的に知りたくて、以前試してみたことがあります。


http://mobile-robots.way-nifty.com/daily_report/ …

結果だけ書くと、
 double * double の計算は int * int と比べて28倍くらい遅い。
 double / double の計算は int / int と比べて42倍くらい遅い。
という結果でした。
(上記はCPUコアがH8/300Hの結果)

求め方は上記のリンクにあるとおりですので、R360-2000さんが使用されているCPUでも同じように計算/実測してみてはいかがでしょうか。

FPU(浮動小数点演算コプロセッサ)をもっているCPUを使うともう少しましだと思いますが、FPUがある場合は割り込み処理をする際にFPU関連のレジスタも一緒に退避させてあげないと割り込みから戻ってきたときに計算結果がおかしくなっていることがあります。
    • good
    • 5

FPUが使える環境では、浮動小数点数を使った方が、むしろコードサイズや処理時間を改善できる可能性があります。



三角関数はともかく、平方根ぐらいなら1命令で実行できることも少なくありませんから、使っている処理系の特性と、実装しようとする処理をあわせて検討する必要があります。それをせずに、盲目的に浮動小数点数の使用を禁止して固定小数点のコードを自作するのは、時期尚早な最適化でしかありません(環境次第では時期尚早な不最適化にもなり得ます)。
    • good
    • 0

みなさんの回答でほぼ出揃ったと思いますが、少し補足を。


組込み系では、容量も処理時間も余裕が無い場合が多く、たまたま十分にある環境であっても
節約する習慣を付けておく(もしくはノウハウを身に付けておく)ことも重要です。
先輩方はそういう意味で実数型を頑なに拒んでいるのではないでしょうか。
実数計算は容量も処理時間も段違いですので。

少し極端な例では、「割り算は時間が掛かるから」という理由で仕様の段階で分母は2の階乗に限定し、
2^0,2^1,2^2,・・・でcase分けをしてビットシフトに持ち込む、ということも実際にありました。
(もちろん整数計算です。)
a=2;
x/=a;

x>>=1;
では実行時間に雲泥の差が出ますので。

組込み系では、常にコードサイズや処理時間を節約することを心掛け、実数型を使うための十分な
妥当性が無い場合は、たとえ要領や時間が十分であっても使わない方が正しいと思います。
    • good
    • 1

>コードサイズが大きくなること、処理時間が大きくなることが理由だと考えていますが、定量的に考察したことがありません。



170バイトのプログラムが、実数型のsin関数を使った瞬間に4700バイトに増えます。

ROMが2KBなら、ROMに焼く事さえ出来ません。

>しかしながら、先輩たちはその使用をかたくなに拒みます。

「まだメモリ空いてるから、冗長なの使っても良いよね」が積み重なると、ある瞬間に「破綻」します。

全員が全員、100バイト節約する努力をせず、上司に「ROMに入りませ~ん」って報告すれば、上司は「CPUをROM領域が2倍の上位チップに変える」とか「ROMチップを2倍にする」って方法を取るしかありません。

ROMの容量が変わったりCPUが変われば、ハードウェアチームにも迷惑を掛けるし、製品のコストアップに直結します。

>もし仮に、コードサイズや処理時間に問題ないとしても実数型を使わない理由を教えていただけませんでしょうか?

組み込み系の鉄則は「99%の余裕があっても、0.1%の削減努力を怠るな」です。

「コードサイズや処理時間に問題ない」ってのは「今は問題ない」ってだけです。「永遠に問題ない状態が続く」訳はありません。どんなに余裕がありそうに見えても「いつか限界が来る」のです。

その限界は「まだ大丈夫だよね」とか「実数使う余裕あるよね」とかっていう「甘え」があればあるほど「より早く訪れる」ことになるでしょう。

実数計算は、確かに「使うと便利」です。でも、便利な物は「一度使うと止められなくなる」ものです。そして、それを使い続けていると「使えない状況に陥った時に、何も出来なくなる」のです。

それに「貴方が書いた、実数演算を使った冗長なコード」は、貴方がその職場から居なくなったとしても、延々と使い続けられます。

1つ、喩え話をしましょう。

ある日ある時、貴方は「かなり前に退社した人が書いた、コメントが殆どないソースプログラム」と「良くわからない資料」を手渡され「現行機種に機能追加するだけの、簡単な仕事だから。既存の部分は変更無しでよろしく」って言われます。

何も追加せずにプログラムをビルドしてみたら、ROMの空きが2キロバイトしかありません。

ですが、自分が作る追加部分は、どうみても2キロバイトじゃ収まりません。

退社した人が書いたソースプログラムを見たら、実数演算しまくりです。結果として必要なのは整数なのに、四捨五入がしたくて実数演算して0.5を足してたりしてます。

貴方は、泣きながら徹夜で「退社した人が書いたソースプログラムを改修して、実数演算を減らし、サイズダウン」をします。もちろん「寸分違わず、同じ動作」をするように改造せねばなりません。

既存部分の改修で忙しく、自分が追加する部分が全然出来てません。でも納期は目の前…。

完成したら「既存部分も手を入れたので、既存部分も検収テストが必要です」って報告も必要。

で、上司から「バカモン!既存の部分は変更無しって言っただろ!何聞いてたんだ!」って怒られます。やりたくてやった訳じゃないのに…。

恐い話だとは思いませんか?

「会社辞めちゃった人」は「ROMが2キロバイトも余ってるんだから、何やっても良いよね」って感じでプログラムを書きました。

「コードサイズや処理時間に問題ないから実数型をガンガン使おう」ってのは、この「会社辞めちゃった人」と同じ考えです。

先輩さん達は「自分が、こういう目に遭いたくない」ので、後輩に対し「余裕があろうがなかろうが、削る手間を惜しむな」っていう教育をします。

貴方が「先輩」になった時、上記の喩え話のような地獄を見たくないなら、後輩に「過去、自分が教わった事と同じ事」を教えた方が良いです。
    • good
    • 4
この回答へのお礼

ありがとうございます。
さすがに、いきなりsin関数を使おうとは私でもしないですが。そこまでの計算をすることがわかっていれば、それが前提のハードを用意することを検討するでしょう。さもなくば、手っ取り早くテーブルを使うでしょうね。

最近は16bitで同じコアでも32~128kまでシリーズ化されているので真ん中の64kあたりを選んで、かつ7割くらいで収まるようにしています。128kになっても値段が倍にはならないでしょうし、あらかじめすべての価格を調べておきます。それでも「1ランク下」でなんとかならない?というときには「次何かあったら1ランクあげてね」というようにしています。これらを2回繰り返せばCPUも世代交代が進んでいて、おのずと新しいのにしようとなるのが、今まででした。

甘え=禁じ手という考えもありますが、最近はマイコンの進化に任せられるところは任せて、新しい機能を実現することに集中したい、ように思います。

お礼日時:2009/03/10 23:30

pic33FJで試してみました。


 int ix,iy ;
 float fx,fy;
 double dx,dy; /*64ビット*/
 ix =ix+iy ; /* CPUクロック4サイクル */
 fx = fx+fy ; /* CPUクロック84サイクル */
 dx = dx+dy ; /* CPUクロック155サイクル */

演算時間のみで言えば
 ix =ix+iy ; /* CPUクロック1サイクル */
 fx = fx+fy ; /* CPUクロック80サイクル */
 dx = dx+dy ; /* CPUクロック143サイクル */
浮動小数点の演算はライブラリのコールで行っています。
浮動小数点を使用する場合はライブラリがリンクされるのでその分コードサイズが増加します。

>コードサイズや処理時間に問題ない
問題なければ使いますが、規模の小さいマイコンでは問題になる事が多々あります。

上記の問題が無い場合でも
浮動小数点演算では非常に値が近い数同士での引き算では有効数字の桁が少なくなります。
大きさが非常に差がある場合には足し算の結果が希望通りにならない事があります。
仮数のビット数以上に数値の桁(2進数での桁)が違っているといくら足しても結果に現れません。
浮動小数点で複数個の数値の加減算を行う場合には数値の大きさを考えて加減算の順番を変えるなどの工夫が必要になる事があります。

参考URLの「精度」の項目も参照してください。

参考URL:http://ja.wikipedia.org/wiki/%E6%B5%AE%E5%8B%95% …
    • good
    • 0
この回答へのお礼

ありがとうございます。
早速URLを見てみます。

>上記の問題が無い場合でも・・・
このような例を教えていただけると非常に勉強になります。
ありがとうございます。

お礼日時:2009/03/10 23:04

こんにちは。


私も先輩方と同じく、組み込みを長年やる中で実数型の使用は頑なに拒んでいます。

◆理由1:遅い
定量的にどうとか以前に、使い物になりませんでした。

◆理由2:整数で十分
計算の仕方を工夫すれば、桁落ち少なく、高速に実行できます。
つまり、精度に問題があるというのではなく、むしろそんな精度は不必要であり、不必要な機能にCPUパワーやコードサイズが食われるのがガマンならん、という事だと思います。
もちろん、数値の精度が要求される開発であれば、少々実行速度とかを犠牲にしても、実数で行うべきとは思いますが・・・。
どうですか?

あと、「誰もやった事が無い」なんて事はないと思います。
恐らく、みんな一様に
実数に期待→使い物にならずに絶望→以後頑なに封印
という道を歩んできたのではないでしょうか。
ただ、上記の事は私の10年以上前の実体験ですので、今現在実験してみる価値は、あると思います。
    • good
    • 1
この回答へのお礼

ありがとうございます。
確認して「使い物にならなかった」という体験は私にもあります。もちろん、そのときは迷わず固定~の計算を使います。

私のような「怖いもの知らず」のすぐ上の先輩は「教えを伝える」がごとく拒むので、それをちょっと柔軟に考えて欲しいと思うことがあります。

ベテランには「そろそろまた考えてみるか」という人がいるので慎重に進めてみようと思います。

お礼日時:2009/03/10 23:02

ハード的に浮動小数点演算回路を持たない場合の固定小数点と浮動小数点の速度の違いは大きいですからね。

昔PS1でfloatを使ったコード書いた人がいて、あまりの遅さに涙してました。固定少数に変えたら劇的に速度が改善しましたが。

>もし仮に、コードサイズや処理時間に問題ないとしても実数型を使わない理由を教えていただけませんでしょうか?
コードサイズや処理時間に問題ないなら、特に使わない理由は無いと思います。ただ、あえて浮動小数点を使って速度がギリギリになるぐらいなら余裕で動く固定小数点をとります。
理由はCPUの処理時間の大半を浮動小数点の処理時間が占有している場合に、演算周りのプログラムを変更して処理が間に合わなくなったら固定小数点への切替を検討する必要が出てきます。これが締め切り間際だったら死にますよ。テストもやり直しだし。それに浮動小数点を使って余裕で間に合うCPUなら、私ならCPUのランクを一つ落とします。その方がコストが減りますからね。
もし、私が浮動小数点を使っても良いと思うとしたら固定小数点を使った場合と速度的に大差が無い、浮動小数点を使ったほうがテストが圧倒的に楽というどちらかの条件が満たされた場合ですかね。
    • good
    • 0
この回答へのお礼

ありがとうございます。

>私が浮動小数点を使っても良いと思うとしたら固定小数点を使った場
>合と速度的に大差が無い、浮動小数点を使ったほうがテストが圧倒的
>に楽というどちらかの条件が満たされた場合

もちろん、CPUの値段を下げることも必要だと思っています。
条件を見極めて、得られるメリットが多くなるように柔軟に考えて仕事ができるようにしたいです。

お礼日時:2009/03/10 22:50

仮に処理時間やコードサイズや誤差の問題がないのなら、私だったら使います。


処理時間やコードサイズや誤差の問題がないのに使わない理由はその先輩にしかわからないでしょう。

ただ、実際のところ、処理時間やコードサイズや誤差の問題がまったくないケースというのは滅多にないかと思いますし、本当に浮動小数点数が必要なケースも滅多にないように思えます。大概は固定小数点で済むはずです。

あと、現時点では問題がなくても、将来を考えて、なるべくコードサイズをコンパクトにしておくということも重要ですしね。
    • good
    • 0
この回答へのお礼

ありがとうございます。
確かに、浮動小数点を使いたい部分は全体の1,2箇所です。
整数に直した後の値で話をするソフト屋さんと、CPUを安くしたいハード屋さん、物理値で話をしたいシステム屋さんの間でよく話題になるので、そろそろ解決したいなという気持ちがあります。
現時点の設計基準も満たしつつ、将来はローエンドのマイコンでも多くの人にわかってもらいやすい=指摘してもらってバグが減るようになって欲しいです。

お礼日時:2009/03/10 22:46

個人的には、必要な場合は使うべきだとは思いますが...



本当に使えないケースとしては次のようなものがあります。

マルチタスク環境で、タスクの切り替え時にFPUレジスタやそれに付随する制御レジスタを退避していない場合があります。
その場合、単一のタスクでのみ浮動小数点数を使うのであれば問題ありませんが、複数のタスクで使うと破綻します。

ちなみに、C言語の規格では、「実数」というのは「虚数」に対しての「実数」ですので整数も含みます。「虚数」というのは、具体的にはdouble _Complexとかdouble _Imaginaryのことです。
    • good
    • 0
この回答へのお礼

ありがとうございます。
マルチタスクを使うような環境ではないのです。
厳密に実数にはそういう定義があったのですね。逆にそのような計算もできたのかと勉強になりました。

お礼日時:2009/03/10 22:41

>処理時間、コードサイズ、精度(誤差)の問題がクリアできれば「使える!」といって差し支えないか心配をしているところです。


>AD値を物理量と関連付けた計算をするときに、32~16bit整数の範囲で何回も係数を掛けたり足したり、あげく桁合わせをしたりとするなら、実数で計算することも検討した方が良いのではないか?と考えています。

実際に試してみる…というくらいしか。
まずは対象CPUで実数型がエミュレートになるかどうかの確認…でしょうか。
エミュレートでも気にするほどの差でなければ実数型でもよいと思われます。
妙な計算式などをいくつも書くくらいなら実数型を使用する方向に傾けた方がコード上で不具合を盛り込む可能性も減るでしょう。
# コンパイラやライブラリの不具合は除きますが。

コードサイズに関しては…
両方のパターンでビルドしてみて、占有するメモリサイズで比較する。くらいでしょう。
処理時間に関しては…おそらく目に見えて差がでることはないかと思われます。

# 既に動いているシステムの場合…大幅な改修はなかなか難しい場合がありますが。
    • good
    • 0
この回答へのお礼

ありがとうございます。
慎重に進めてみたいと思います。

お礼日時:2009/03/10 22:38

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています