• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:処理が異常に遅い原因はわかりますか?)

処理が異常に遅い原因はわかりますか?

wormholeの回答

  • wormhole
  • ベストアンサー率28% (1625/5665)
回答No.2

>例えでいえば、同じことをする数文字のperlの正規表現処理の数100倍の時間がかかっていました。 正規表現そのものには文字列コピーのような機能はないですけど具体的にはどんな処理なんでしょう? またgccのバージョンも書かれた方がよいかと思います。 FreeBSD 9のgcc 4.7.3だと void func1(char *d, char *s, int n) { for (int i = 0; i < n; i++) { *d++ = *s++; } } void func2(char *d, char *s, int n) { for (int i = 0; i < n; i++) { } } void func3(char *d, char *s) { for (;*d++ = *s++;) { } } で出力されるコードはこんな感じです。 .text .p2align 4,,15 .globl func1 .type func1, @function func1: .LFB0: .cfi_startproc xorl %eax, %eax testl %edx, %edx jle .L1 .p2align 4,,10 .L5: movzbl (%rsi,%rax), %ecx movb %cl, (%rdi,%rax) addq $1, %rax cmpl %eax, %edx jg .L5 .L1: rep ret .cfi_endproc .LFE0: .size func1, .-func1 .p2align 4,,15 .globl func2 .type func2, @function func2: .LFB1: .cfi_startproc rep ret .cfi_endproc .LFE1: .size func2, .-func2 .p2align 4,,15 .globl func3 .type func3, @function func3: .LFB2: .cfi_startproc .p2align 4,,10 .L10: movzbl (%rsi), %eax addq $1, %rsi movb %al, (%rdi) addq $1, %rdi testb %al, %al jne .L10 rep ret .cfi_endproc .LFE2: .size func3, .-func3 ほぼ#1の方のおっしゃってる通りですね。

ymda
質問者

お礼

ありがとうございます。 アセンブラリストを出してから、時間とれなくなってしまいました。。汗 FreeBSDのシステムコンパイラ gcc4.2ですと、-O2でも-O3でも この回答の2倍以上程度のコードになってしまっているようですが、 gcc4.8、4.7.3を試したら、それなりの速度に戻ってくれました。 また、わずかながら、gccよりもllvm-gccのが速い感じもしています。

関連するQ&A

  • C言語です。コレを使ってなにかプログラミングを組んでください

    C言語です。コレを使ってなにかプログラミングを組んでください よろしくお願いします 何でも構いません #include<stdio.h> void str_copy( char dst[], char src[] ) { int i; for (i =0; src[i] != '\0'; i++) { dst[i] = src[i]; } dst[i]= '\0'; }

  • strcpy関数について(\0のコピー)

    '\0'のsrcからdstへのコピーについて考えて見たのですが、 char *strcpy(char *dst,const char *src) { int i=0; for(i=0;src[i]!='\0';i++) dst[i]=src[i]; dst[i]=src[i];←1 return dest; } このプログラムではfor文の真偽値の判定の段階では'\0'がsrcからdstにコピーできていないので1のdst[i]=src[i]でコピーする必要がありますが、以下のようにプログラムを変更すると char *strcpy(char *dst,const char *src) { int i=0; for(i=0;(dst[i]=src[i])!='\0';i++) ; return dest; } (dst[i]=src[i)の代入式の段階でsrcからdstにコピーしその後でfor文の真偽値の判定をするので、真偽値判定前にdst側配列に'\0'が入っていると言う考えでこのプログラムを理解して良いのでしょうか。なにかミスしそうなプログラムですが、考え方として、私の言っている事は正しいでしょうか。宜しく回答願います。

  • c言語 iconv

    msys環境で実行して,指定されたファイルの文字コードをShift-JISに変換して表示するコードを作成しているのですがうまく表示されません.何がいけないのでしょうか.第1引数に変換対象のファイル名,第2引数にファイルの文字コードを指定しています. #include <stdio.h> #include <string.h> #include <iconv.h> int main(int argc, char *argv[]) { iconv_t conv; char src[10000]; char dst[10000]; int src_len = strlen(src); int dst_len = sizeof(dst) - 1; char *buf_in; char *buf_out; FILE *fp; fp = fopen(argv[1], "r"); if(NULL == fp) { printf("ファイルを開けません\n"); } else { while(fgets(src, 10000, fp) != NULL) { buf_in = src; buf_out = dst; /* 変換器を作成 */ conv = iconv_open("Shift-JIS", argv[2]); /* 変換 */ iconv(conv, &buf_in, &src_len, &buf_out, &dst_len); *buf_out = '\0'; /* 終末処理 */ /* 文字コード後の文字列を表示 */ printf("%s\n", dst); } /* 変換器を終了 */ iconv_close(conv); /*ファイルを閉じる*/ fclose(fp); } return 0; }

  • ConvertINetStringについて

    wininetのInternetReadFileでUTF-8のサイトから文字列を受け取ったところ、2バイト文字が文字化けしていました。 ConvertINetStringでUTF-8からShift_JISに変換しようとしていますが上手くいかず困っています。 プログラムは下のようになっています。 DWORD mode = 0, readSize; char src[1024]; BYTE dst[1024]; int srcLen, dstLen; char c[1024]; while( true ) { readSize = 0; ::ZeroMemory(src, sizeof(src)); ::ZeroMemory(dst, sizeof(dst)); // 受信 InternetReadFile( hRequest, src, sizeof(src), &readSize ); if(readSize == 0) break; srcLen = strlen(src); dstLen = sizeof(dst) - 1; // UTF-8からShift_JISへ ConvertINetString(&mode, 65001, 932, src, &srcLen, dst, &dstLen); // BYTEからcharへ for(int i = 0; i < strlen(dst); i++) c[i] = (char)dst[i]; Console::WriteLine("受信:{0}", gcnew String(dst)); } 1.ConvertINetStringでdstに値がちゃんと入らない(「・」みたいなゴミのような文字が入ります) 2.本題とは逸れるのですが、BYTEからcharへの変換はこれでいいのでしょうか? ConvertINetStringが上手くいかない理由が特にわからないので回答をもらえたらありがたいです。

  • ポインタ変数を用いた配列の反転操作。

    strSrcの文字列を逆順にしてstrDstに格納し、 逆順にした文字列を表示するプログラムを自分なりに考えて、 作成したのですが、途中で行き詰ってしまいました。 src=strSrc;とdst=strDst;辺りが上手くいっていないようなので どなたかどのように記述すれば良くなるのかご教授お願いします。 また、他の問題点などもあればどうかご指摘お願いします。 #include <stdio.h> /* 文字列反転関数 引数: char *src : 反転させる文字列 char *dst : 反転させた結果を書き込む文字列 返値: なし */ void reverseStr(char *src, char *dst) { src=strSrc; dst=strDst; /*文字列の末尾を指すまでインクリメント*/ while(src != 0){ src++; } /*『配列strDstの番地の値』を『配列strSrcの番地の値』に上書き*/ while(*dst != 0){ *dst=*src; src--; dst++; } *dst=0; } /* メイン関数 引数: なし 返値: int 正常終了時 0 */ int main(void) { char strSrc[] = "abcdefghijkl" ; char strDst[] = "01234567890123456789" ; reverseStr( strSrc, strDst ) ; printf("%s\n", strDst ) ; return( 0 ); }

  • c言語の文字列の逆順のプログラムがわかりません

    文字列を逆順して出力するプログラミングがわかりません。 #include <stdio.h> #include <string.h> void reverse(char *moji, char *gyaku); int main(void) { char x[30]; char y[30]; puts("文字を入力してください。\n"); scanf("%s", x); reverse(x, y); printf("逆順すると%sです。\n", y); return (0); } void reverse(char *moji, char *gyaku) { int i, len; len = strlen(moji); gyaku = moji + len - 1; for(i = 0; i < len; i ++){ putchar((int)*gyaku); gyaku--; } } 理想とする実行結果は 文字を入力してください。 abcdefg 逆順するとgfedcbaです。 なんですが、 上記のソースを実行すると 文字を入力してください。 abcdefg gfedcba逆順すると(謎の漢字)です。 となります。 どこがおかしいんでしょうか? よろしくおねがいします。

  • ファイルへの書込み処理が異常に遅い

    以下のファイルへの書込みを行なうプログラムの処理速度が極端に遅く困惑しています。 -------------------------------------------------------------------------------- /*  文字列"0,"をファイルに約2MB出力するプログラム  (2000文字で改行、1行毎にfopen&fclose) */ #include<stdio.h> void main( int argc, char *argv[] ) {   FILE *fp;   for( int i = 0; i < 1000; i++ )   {     if( !(fp = fopen( "C:\hogehoge.log", "a" ) ) )     {       exit( 1 );     }     for( int j = 0; j < 1000; i++ )     {       fprintf( fp "0," );     }     fprintf( "\n" );     fclose( fp );   }   exit( 0 ); } -------------------------------------------------------------------------------- 処理時間は5分程度です。 出力する文字列を"0#"に変えると5~6秒で終了します。 カンマが入ると違うのでしょうか? OSはWinXP、コンパイラはVC++7.0です。 原因と解決策をご存知の方、よろしくご教示下さい。

  • C言語の課題で困っています;

    C言語の課題で困ってます; 学校の課題で、キーボードから文字を入力する(最大80文字)。入力された文字列と、入力した文字列を逆順にした文字列を表示する。(malloc,freeを使って作成して下さい) ヒントで #invlude <stdio.h> void main(void){ char *buf; //入力文字列用 char *seq; //入力文字列用コピー用 char *rev; //逆順文字列用 int lec, i; buf =(char*)malloc(81); printf("文字列を入力:"); scanf("%s"buf ); for(i = 0; buf[i] ??? '\0'; i++){ } Ien = i; /* lenに文字列の長さが入る */ seq = ???(??? + 1); /* len+1文字文確保*/ for(i = 0; ???; i++){ seq[0] = buf[0]; } free(buf); rey = ???(len + 1); for(i = 0; < len; i++){ rev[len - i - 1] = seq[i]; } ren[i] ~ '\0'; printd("入力文字列 : %s\n",sep); でたんですが、全然分からなくて足りない部分の答えを教えてもらえると助かります;

  • インラインアセンブラについて

    現在、インラインアセンブラを学んでいるものです。 開発環境は Visual Studio 2005 です。 プログラムは、unsigned char型の配列を3つ(src1, src2, ans)用意し、src1[i] + src2[i] = ans[i] というようにiを変数として、src1、src2それぞれの要素の加算を配列ansに格納する動作をインラインアセンブラで作成しています。 そして、高速化を目指しMMXを使用しているのですが、うまく動作しません。 動作結果としては配列ansに正しい解が代入されず、全ての要素が 205? になっています。 どこかに問題があるのですが、未熟な自分では間違いに気づくことができません。 ご指摘お願いいたします。  #include <stdio.h> #include <stdlib.h> #include <string.h> #define LEN 64 int main(void){ unsigned char *src1, *src2, *ans; unsigned char *t1, *t2, *t3; int i, j; src1 = (unsigned char *)malloc(sizeof(unsigned char) * LEN); src2 = (unsigned char *)malloc(sizeof(unsigned char) * LEN); ans = (unsigned char *)malloc(sizeof(unsigned char) * LEN); t1 = src1; t2 = src2; t3 = ans; i = LEN / 8; for(j=0; j<LEN; j++){ //配列src1、src2の初期化 src1[j] = j; src2[j] = j + 1; } _asm { mov ecx, i LOOPSTART: movq mm0, src1 movq mm1, src2 paddusb mm0, mm1 movq ans, mm0 add src1, 8 add src2, 8 add ans, 8 loop LOOPSTART emms } src1 = t1; src2 = t2; ans = t3; for(i=0; i<LEN; i++) printf("%d + %d = %d\n", src1[i], src2[i], ans[i]); return 0; }

  • アルファベットを入力するとすべてのアルファベットを小文字に変換して出力

    アルファベットを入力するとすべてのアルファベットを小文字に変換して出力するプログラムを作成しました。2度以上同じ処理を行う場合はその部分を関数としなければいけないのですが、実行結果のように出力できませんでした。。どこが間違っているのでしょうか? 実行結果↓ ************ AOmori ==>aomori iwate ==>iwate AKITA ==>akita ************ #include <stdio.h> #include <string.h> #include <ctype.h> int henkan(void); int main(void) { char str[100]; int j,len; for(j=0;j<6;j++){ gets(str); printf("==>"); } henkan(); return 0; } int henkan(void) { char str[100]; int i, chk,len; for(i=0;i<len;i++){ chk=isupper(str[i]); if(chk!=0)str[i]=tolower(str[i]); { printf("%c",str[i]); } } printf("\n"); return chk; }