質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.54%

  • C

    4397questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

clock関数を使った問題

解決済

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 848

deadline444

score 3

int型の変数どうしの積とdouble型の変数どうしの掛け算1回あたりの実行時間を10万~1000万回程度と多数回繰り返し計算するのに要する時間の総和から演算以外の部分(繰り返しや代入)にかかる時間を除外して純粋に積演算にかかる時間を推定するプログラムを作成し,それぞれの実行時間の比較を行うという問題です。
結果が負になってしまいます。どこを改善すればよいでしょうか?

include <stdio.h>

include <stdlib.h>

include <time.h>

int
main(void)
{
clock_t cl1, cl2, cl3, cl4, cl5, cl6, cl7, cl8;
int i, s;
double j, p;
/*全体(int)*/
cl1 = clock();
for (i = 0; i < NLOOP; i++) {
s = i * i;
}
cl2 = clock();

/*代入, 繰り返し(int)*/
cl3 = clock();
for (i = 0; i < NLOOP; i++) {
s = i;
}
cl4 = clock();

printf("int型の掛け算のみにかかる時間%f [μs]\n",( ((double)(cl2 - cl1) / CLOCKS_PER_SEC) -  ((double)(cl4 - cl3) / CLOCKS_PER_SEC) ) * 100);

/*全体(double)*/
cl5 = clock();
for (j = 0; j < NLOOP; j++) {
p = j * j;
}
cl6 = clock();

/*代入, 繰り返し(double)*/
cl7 = clock();
for (j = 0; j < NLOOP; j++) {
p = j;
}
cl8 = clock();

printf("double型の掛け算のみにかかる時間%f [μs]\n",( ((double)(cl6 - cl5) / CLOCKS_PER_SEC) - ((double)(cl8 - cl7) / CLOCKS_PER_SEC) ) * 100);

return 0;
}

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+2

そもそも考え方が違くないですか?
代入の総時間から積演算の総時間を引いたら、そりゃマイナス値にもなるでしょう(代入の方が軽いから)
処理は4つある。
int型の積演算
int型の代入
double型の積演算
double型の代入
で、積演算については、ループ処理を除いた純粋な演算部分のみの時間を求める。
代入については、ループ処理を除いた純粋な演算部分のみの時間を求める。
つまり、ロジックとしてはこうじゃないでしょうか(時間部分は簡略してmsにしています)

cl = 0;
for (i = 0; i < NLOOP; i++) { 
    cls = clock(); 
    s = i * i;
    cle = clock(); 
    cl += (cle - cls);
} 
printf("演算のみ %ldms\n", cl);

上記はint型の積演算部分のみですが、他の3つについても同様の考え方です。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/19 08:38

    成る程分かりました。
    ありがとうございます。

    キャンセル

  • 2017/01/19 10:03

    ベストアンサーが付いた後で申し訳ないのですが、論理的には正しいように思えますが、実際にはそれでは正確には計測できません。一般に出回っているPCでマシンサイクル単位で時間が計測できる処理系はおそらく存在しないと思います。`clock`関数が返す値は、Linux(gcc)ならマイクロ秒、Windows(VC++)ならミリ秒単位です。したがって、`s = i * i`1回分の時間を計測することは不可能です。また、`clock`関数の呼び出し自体が掛け算と比べればそれにかかる時間など無視できるぐらいに遅いので、仮に計測できたとしても、それは`clock`関数の処理時間ということになってしまいます。

    キャンセル

  • 2017/01/19 10:07 編集

    技術的にはおっしゃる通りだと思いますが、あくまでも何かの課題(問題)なので、そこまで技術的なことを求めているのではないと思います。
    正確には測れないかもしれないけど、ロジック的にはどう考えればいいの?くらいの課題と読み取り回答しました。

    キャンセル

  • 2017/01/19 10:10

    もちろん質問者様が、「そんな簡単なことではない」「きちんと正確に測りたいんだ」というなら他の回答を参考に実装していただければ良いです。

    キャンセル

  • 2017/01/19 11:29

    丁寧にありがとうございます。

    キャンセル

  • 2017/01/19 13:10

    ttyp03 さん

    > あくまでも何かの課題(問題)なので

    であるなら、質問文を読む限り、やはり基本的な考え方は質問者さんのコードで正しいと思うのですが……。

    キャンセル

  • 2017/01/19 13:14

    質問者様のコードは、
    (ループ処理を含む積演算の総時間)-(ループ処理を含む代入処理の総時間)
    を算出めています。
    それがどうして問題文にある「純粋に積演算にかかる時間」になるのでしょうか。

    キャンセル

  • 2017/01/19 13:38

    ttyp03 さん

    > それがどうして問題文にある「純粋に積演算にかかる時間」になるのでしょうか。

    同じ条件で両者の時間を計測した場合、その差分が処理の違いによる差分と考えるのは理にかなっていると思います。
    また、問題文には「多数回繰り返し計算するのに要する時間の総和」と書かれていますので、ループの開始から終了までの時間を計測すると考えるのが自然です。それに「演算以外の部分(繰り返しや代入)にかかる時間を除外して」という文言からも、計測の範囲にはfor文も含まれると考えられます。

    出題者は、問題を解かせる以上、実際に検証できなければ困るわけで、検証不可能な回答にはならないだろうというのが私の考えです。

    キャンセル

  • 2017/01/19 13:49

    論理で考えれば確かに質問者様のコードでも正しいような気はしてきました。
    要は、
    (ループ処理を含む積演算の総時間)-(ループ処理を含む代入処理の総時間)
    ではなく、
    (ループ処理を含む積演算と代入処理の総時間)-(ループ処理を含む代入処理の総時間)
    だから、積演算部分のみの時間が計算できるという理論ですね。今わかりました(すみません)
    だとしても結局は他の回答にあるように細かいチューニングをしないと正しく計測できないわけですから、課題程度にそこまで求めているんでしょうか。
    こればかりは出題者に聞くしかないですが。

    キャンセル

+1

こんにちは。

もし、リリース・ビルドされているのでしたら、最適化されてs=i*i;等の計算が最後だけしか行われていないかも知れません。
sやpにvolatileをつければ最適化を抑止できます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

単純に、「誤差の範囲よりかかる時間が少ない」だけではないかと思います。

多くのOSはマルチタスクですので、裏で動く処理の加減などで、全く同じプログラムでも所要時間は変化します。

そして、x64ではSSE2までが標準命令に入り、浮動小数点数ですら乗算のスループットは2クロックというレベルです(Intelの資料PDF)。

ということで、「乗算の速度」は想像を絶する回数を測定しないと、有意な結果は得られないと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

時間計測の誤差により、s = i * i(p = j * j)の方の時間よりもs = i(p = j)の方の時間が上回ったためです。
実際のところ、今時のCPUは掛け算の演算速度が非常に速いので、for文と変数への代入の処理にかかる時間に比べれば誤差程度にしかなりません。その誤差がたまたま後者で上回ると、当然のことながら結果は負数になってしまいます。

この手の計測をする場合、できるだけ誤差の要素を減らすためにfor文の中の処理を1回だけでなく複数回(10回とか)実行させることが多いです。

こんな感じ

/*全体(int)*/ 
cl1 = clock(); 
for (i = 0; i < NLOOP; i++) { 
    s = i * i; 
    s = i * i; 
    s = i * i; 
    s = i * i; 
    s = i * i; 
    s = i * i; 
    s = i * i; 
    s = i * i; 
    s = i * i; 
    s = i * i; 
} 
cl2 = clock(); 

/*代入, 繰り返し(int)*/ 
cl3 = clock(); 
for (i = 0; i < NLOOP; i++) { 
    s = i; 
    s = i; 
    s = i; 
    s = i; 
    s = i; 
    s = i; 
    s = i; 
    s = i; 
    s = i; 
    s = i; 
} 
cl4 = clock(); 


※最適化オプションは考慮していません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • C

    4397questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。