プロが教える店舗&オフィスのセキュリティ対策術

CQ出版のインタフェース 2017-5 の記事のプログラム例に
for( i=0; i<256; i++){
 for( y =0; y < Y; y++ ){
  for( x = 0; x < X; x++){
   p[0] = img -> imageData[img->widthStep* y + x*3 ]; //B(青色)
   if(p[0]==i){hn[i]++;}
  }
 }
}
がありました。このリストを見て、無性にイライラするのは私だけでしょうか?

なぜ、i,y,x の3重のループで処理しないといけないのか、y,xの2重ループで十分ではないかと思います。

for( y =0; y < Y; y++ ){
 for( x = 0; x < X; x++){
  p[0] = img -> imageData[img->widthStep* y + x*3 ];  //B(青色)
  hn[ p[0] ]++;
 }
}

3重にするならせめて、y,x,i の順にしてp[0]への代入は1回で済ませればと思います。

for( y =0; y < Y; y++ ){
 for( x = 0; x < X; x++){
  p[0] = img -> imageData[img->widthStep* y + x*3 ];  //B(青色)
  for( i=0; i<256; i++){
     if(p[0]==i){hn[i]++;}
  }
 }
}

最近のコンパイラの最適化では、私の書いたようなコーディング(修正?)は無意味なのでしょうか?

A 回答 (7件)

貧乏じーさんプログラマです。



3重ループにしたのは紙面に余白が無かったからでしょう。
(○ページ以内でよろしく、みたいな。)

コードチェッカーとしては(私的にですが)3重ループ以上なんて許しません(たとえ3次元空間でも)。
もちろん2次元配列や、まさか3次元配列なんて、文法的に許されても常識的には使わない手法です。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

>3重ループにしたのは紙面に余白が無かったからでしょう。
イライラを軽減する解釈ありがとうございます。
でも、今回は該当しない感じです。

別の解釈ありましたら、よろしくお願いします。

お礼日時:2017/04/06 20:35

30年ほどシステム開発の仕事をしていました。


処理したいことを明示的、直感的に示していればループの段数とか順番にこだわりません。
仕事仲間に「ソースコードはエッセーだ!」と言っている人間がいました。
ある意味そうだなぁと思います。
同じことをするにも幾つかのやり方がある場合が多く、何を選ぶかはその人の視野、経験、物の見方、そして最後に「好み」があると思うからです。

雑誌の例題とかは一般的なプログラム開発と違いソースコードを書く前に実装仕様を文書で示しませんので、意味合いをより明確に示せる書き方が好ましいと考えます。
ですので、ご質問に書かれている雑誌に掲載されていたコードが、処理の意味合いをより多くの人がソースコードを見て「こういうことをするのはこうすればよい」と容易に理解できる視点で出来ていれば私的には「なるほどね」と思うだけです。

参考まで。
    • good
    • 2
この回答へのお礼

回答ありがとうございます。

>同じことをするにも幾つかのやり方がある場合が多く、何を選ぶかはその人の視野、経験、物の見方、そして最後に「好み」があると思うからです。
同感です。ですから、人の書いたコードを読むのは、一つの楽しみになっています。

今回の事例は、筆者はいったい何を考えているのか? といったイライラが質問の発端です。言い換えれば、
>「こういうことをするのはこうすればよい」と容易に理解できる視点で出来ていれば
の前提条件が、本件では満たさないのがイライラの一因に思えますが、その点はいかがでしょう?
お礼を書きながら考えてみました。
 「輝度値がiの画素ならば、hn[i]++ する」
という処理をなぜ、
 「一番外側でiをループで回して、輝度値とiが一致したときhn[i]++する」
というコードが わかりやすいコード になることが理解できないです。
わざわざ、効率の悪いコードを書いている気がしてならないのですけど・・
ループに回すならせめて一番内側で回してほしいと感じてしまうのです。

お礼日時:2017/04/06 20:33

処理速度が特に問題にならない、かつi=0~255の繰り返しをx,yの繰り返しの外側で行うほうが業務的に判りやすいなら、2017-5 の記事のプログラム例で問題がないかと思います。



但し、処理速度の観点からいえば、
あなたがかかれた2重ループの方法がベストかと思います。
(但し、p[0]の値が0~255であることが保障される場合です。保障されないなら、3重ループがベストになるかと)
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

>保障されないなら、3重ループがベストになるかと
保障されないなら、ループではなく
 if(0<=p[0] && p[0]<=255) {
の条件判定と思いますけど、という突っ込みはさておいて、

>外側で行うほうが業務的に判りやすいなら、
なるほど「業務的に判りやすい」ですね。そういう解釈、感謝です。

お礼日時:2017/04/07 09:41

利点を考えてみました




これを並列処理したときに
スレッド0: hn[0] に p[0] = 0 をカウント
スレッド1: hn[1] に p[0] = 1 をカウント
...
とすれば、
・img -> imageData は読み出すだけなので衝突しない
・hn[i] でアクセスする領域は、スレッド毎に i が違うので、同じ箇所に書き込まれることはない。
となり、排他処理が不要となります。
(もちろん、x,y,i,p[0]はスレッドでローカルな変数とします)

ただ、並列処理のオーバーヘッドや同時並列処理数等を考えると、こんな並列処理はしない方が効率的です。


あるいは、hn[]がシークに時間がかかる領域の場合、
hn[p[0]) で毎回違う位置を探しに行って、その時間が無視できないほどだったら、
先にhnを決めてしまった方が速くなるでしょう。

こちらも、非現実的です。
    • good
    • 0
この回答へのお礼

回答ありがとうございます

>利点を考えてみました
かなり苦しい解釈ですが、並列処理ですね、ありがとうございます。

お礼日時:2017/04/07 09:46

No.2です。



> 今回の事例は、筆者はいったい何を考えているのか? といったイライラが質問の発端です。言い換えれば、
> >「こういうことをするのはこうすればよい」と容易に理解できる視点で出来ていれば
> の前提条件が、本件では満たさないのがイライラの一因に思えますが、その点はいかがでしょう?

当方は「インタフェース2017-5」を購読していませんので詳しい内容はわかりません。
No.2にも同様のことを書きましたが、この3重ループが「このプログラムがやりたい事の処置手順」を分かりやすく示しているのであればそれでよいと思います。
それだけです。それにつきます。
で、それを満たしていれば自分の考え方とは違っていても「そういう見方もあるのか」と感じるだけで、イライラしたり「自分ならこうする」と強く主張したりはしません。
プログラムのロジックは仕様書の処理方式の記述内容に従っていたとしても最終的にはコーダーの観点が反映されるものだと思いますので、それをはなから否定して「こあらねばならない」ということはぜずコーダーの話を(説明を)聞きます。仕事の現場では後輩や部下に対してそのように接していました。
なお、現役時代はリアルタイム処理のように時間勝負の処理ではない限り「凝ったことは考えず出来るだけ平易に」、「コメントも分かりやすく」、「ソフトウェアは時に人より長生きするから」(←自分の転属・転職・退職の後も誰かが保守する等の意味合い)と指導していました。最初に書きました『この3重ループが「このプログラムがやりたい事の処置手順」を分かりやすく示しているのであればそれでよい』はそういう観点でのものです。

ちなみに雑誌などに掲載するプログラムとしては仕方ないですが、実プログラムとそしては256は直値ではなく意味が明示的に分かるものにdefineしたいですね。(^^;
変数等の名前も工夫したいし。。。
    • good
    • 0
この回答へのお礼

再度の回答ありがとうございます。

>それを満たしていれば自分の考え方とは違っていても「そういう見方もあるのか」
>と感じるだけで、イライラしたり「自分ならこうする」と強く主張したりはしません。
まったく同感です。ほとんどの場合は、その通りです。
前のお礼に書いたように、「そういう見方もあるのか」を知ることは、人の作ったプログラムを読む楽しみの一つでもあります。
普通であれば、馬鹿だなこのプログラマ、で終わるのですが、掲載された雑誌が
CQ出版のインタフェース 2017-5なので、私の配慮不足で何か意義があるのでは、と深読みをして、これといった解釈が得られずに無性にイライラして質問した次第です。

今回質問した案件では、前提条件の、
「このプログラムがやりたい事の処置手順」を分かりやすく示している
とは思えないので、No3さんや、No4さんの回答のように、
 私が気が付かないメリット、
 なるほど「そういう見方もあるのか」といった見方
を教えていただきたく質問しています。

お礼日時:2017/04/07 11:57

単純に処理量が256倍になるよね。


こういうのはスラッジと言ってバグと同じ扱い。
処理量が倍くらいとは別の次元なので
コードレビューやデスラッジで取り除くべきものです。

グラフィックスは速度が使い勝手に響きやすいので、
グラフィックスのプロジェクトではデスラッジは
は重要な工程の一つです。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
>こういうのはスラッジと言ってバグと同じ扱い。
スラッジという言葉、初耳ですが、業界(?)ではバグと同じ扱いなのですね。心強い回答ありがとうございます。

お礼日時:2017/04/10 10:13

http://www.dafont.com/syawal-khidmat.font

これかぁ。


> // 最大となるピンの画素数を獲得

とあるので、おそらく著者は

「最大となるピンの画素数を獲得」

というプログラムが必要と考え

最大ピンの画素数=0
for ( 全ての色レベル について ) {
 if 該当色レベルの画素数>現在の最大ピンの画素数 then
  最大ピンの画素数 = 該当色レベルの画素数 に更新
 end if
}

というアルゴリズムに辿りついた。
ここで「該当色レベルの画素数」をどうやって調べるか、というときに

最大ピンの画素数=0
for ( 全ての色レベル について ) {
 「該当色レベルの画素数を数える」 ← ここ
 if 該当色レベルの画素数>現在の最大ピンの画素数 then
  最大ピンの画素数 = 該当色レベルの画素数 に更新
 end if
}

として、これをそのままプログラムにした。
というところでしょうか。


この通りなら、著者の考え通りのプログラムということになります。
効率はともかく。
    • good
    • 0
この回答へのお礼

さらなる回答ありがとうございます。

教えてくださったページ、意味不明です・・

> // 最大となるピンの画素数を獲得
そのようなコメントはソースリストにないですが、
「該当色レベルの画素数を数える」
という処理が 筆者の基本パターン として刷り込まれていれば可能性ありますね。

お礼日時:2017/04/10 10:09

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