- ベストアンサー
プログラムの機能変えずに高速化 | 質問文章要約
- プログラムemboss.cの機能変えずに高速化したい。画像のメモリ確保はヒープ領域で動的に行い、結果画像は変わらない。消費時間短縮を目指し、改善点を教えてください。
- 消費時間短縮を目指すため、プログラムemboss.cの機能変更せずに高速化したい。画像メモリはヒープ領域で動的確保し、結果画像は変わらない。改善点を教授してください。
- プログラムemboss.cの機能変えずに高速化したい。画像メモリはヒープ領域で動的確保し、結果画像は変わらない。消費時間短縮を目指して改善点をご教示ください。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
emboss関数しか見ていませんが... 間接参照が多すぎます。 ループを回すごとに右端の次元の添え字をインクリメントしているだけなので、ポインタで書き換えましょう。 他にも、dxやdyに絡む演算のうち、ループの外に出せるものは出してしまいましょう。コンパイル結果を見ればわかると思いますが、意外に最適化が効いていないものです。 後は、GCCのターゲットや、実際の実行環境次第になりますが... 一番内側のループは3回程度であれば開いてしまうのも効果があるかもしれません。 配列の要素を、UCHARではなくintにすることで、汎整数拡張によるオーバーヘッドがなくなります。ただし、そもそも汎整数拡張のオーバーヘッドがない、またはほとんどない環境もありますし、キャッシュのヒット率が低下する可能性もあるので要注意です。 細かな部分は他にもありますが、大体こんなところかと思います。 ところで、提示されているURLをクリックしただけではソースが開きません。また、質問文が編集される可能性も高いので、この質問にソースを補足してください。
その他の回答 (2)
- Interest
- ベストアンサー率31% (207/659)
http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/4193.txt これ、アクセスできませんでした。 別なところでソース出してもらえますか?
補足
以下がソースです。 長いので分割します。 #include <stdio.h> #include <stdlib.h> #include <string.h> typedef unsigned char UCHAR; /* 画像サイズは変更不可 */ #define DIM1 960 /* 行数 */ #define DIM2 1280 /* 列数 */ #define DIM3 3 #define RED 0 #define GREEN 1 #define BLUE 2 #define N_REPEAT 200 /* 繰返し回数.消費時間測定時は必ず200とする. */ /* 動的確保されたCSQ形式の画像メモリからppmフォーマットの画像ファイルを作成(通常は未使用) */ void write_ppm_csq_mem(UCHAR ***,char *,int ,int); /* 動的確保されたCIP形式の画像メモリからppmフォーマットの画像ファイルを作成 */ void write_ppm_cip_mem(UCHAR ***,char *,int ,int); /* エンボス処理 */ void emboss(UCHAR ***, UCHAR ***, int, int, int, int); /* ppmフォーマットの画像ファイルを動的確保したCIP形式の画像メモリに読み込み */ void read_ppm_cip_mem(UCHAR ***, char *, int *, int *); /* 3次元配列の動的生成 */ UCHAR ***malloc3Duchar(int ,int ,int ); /* 3次元配列の解放 */ void free3Duchar(UCHAR ***); /* エラー処理 */ void error1(char *); /***** 注意点 *****/ /* 画像のためのメモリはヒープ領域に確保すること(宣言は利用不可とする) */ /***** 注意点 *****/ int main(int argc, char *argv[]) { int i; int dx; /* 横方向シフト量 */ int dy; /* 縦方向シフト量 */ int max_gyou; /* 入力画像の行数 */ int max_retu; /* 入力画像の列数 */ char in_fname[200]; /* 入力画像ファイル名 */ char out_fname[200]; /* 出力画像ファイル名 */ UCHAR ***org,***res; if(argc < 4) /* 入力コマンドチェック */ { printf("usage: a.out filename dx dy \n"); exit(1); } else { strcpy(in_fname,argv[argc-3]); /* 入力画像のファイル名 */ dx=atoi(argv[argc-2]); /* 横方向シフト量(右が正) */ dy=atoi(argv[argc-1]); /* 縦方向シフト量(下が正) */ } org=malloc3Duchar(DIM1,DIM2,DIM3); /* 入力画像用3次元配列の動的確保 */ res=malloc3Duchar(DIM1,DIM2,DIM3); /* 出力画像用3次元配列の動的確保 */ read_ppm_cip_mem(org, in_fname, &max_gyou, &max_retu); /* 画像をファイルより読み込み */ if((max_gyou != DIM1) || (max_retu != DIM2)) /* 読み込んだ画像の行数と列数のチェック */ error1("Image size is wrong."); /* エンボス処理(時間測定のため必ず200回行う.) */ for(i=0;i<N_REPEAT;i++) { emboss(res,org,dx,dy,max_gyou,max_retu); } in_fname[strlen(in_fname)-4]='\0'; /* 入力画像ファイル名から.ppm除く */ sprintf(out_fname,"/tmp/%s_out.ppm",in_fname); /* 出力画像ファイル名設定 */ write_ppm_cip_mem(res,out_fname,max_retu,max_gyou); /* 出力画像をファイルへ出力 */ free3Duchar(org); /* 入力画像用3次元配列の解放 */ free3Duchar(res); /* 出力画像用3次元配列の解放 */ return 0; } /* エンボス処理 */ void emboss(UCHAR ***ans, UCHAR ***org, int dx, int dy, int n_gyou, int n_retu) { int g,r,m; int val; for(g=0;g<n_gyou;g++) /* 1画素ずつ処理する */ for(r=0;r<n_retu;r++) /* 画像メモリ領域外にアクセスしないようにチェック */ if((g+dy >= 0) && (g+dy < n_gyou) && (r+dx >= 0) && (r+dx < n_retu)) for(m=0;m<3;m++) { val=org[g][r][m]-org[g+dy][r+dx][m]+128; if(val > 255) /* 画素値は0以上255以下 */ ans[g][r][m]=255; else if(val < 0) ans[g][r][m]=0; else ans[g][r][m]=val; } else /* 算出できないところの画素値は128とする */ for(m=0;m<3;m++) ans[g][r][m]=128; } /* ppmフォーマットの画像ファイルを動的確保したCIP形式の画像メモリに読み込み */ void read_ppm_cip_mem(UCHAR ***data_buf, char *fname, int *max_gyou, int *max_retu) { FILE *fp ; char str_buf[1024] ; char magic_num[8] ; /* マジックナンバー */ int max_val ; /* 画素値の最大値 */ int count_limit;
補足
続きです。 /* ファイルを開く */ if((fp = fopen(fname, "rb")) == NULL) { fprintf(stderr, "file(%s) can't open.\n", fname) ; exit(1) ; } /* マジックナンバー読み込み */ count_limit=0; sprintf(str_buf,"#"); while((str_buf[0]=='#') || (str_buf[0]=='\n') || (str_buf[0]=='\t') || (str_buf[0]==' ')) { fgets(str_buf,1024,fp); count_limit++; if(count_limit > 1000) { fprintf(stderr,"ERROR: Irregal file format.\n"); exit(1); } } strcpy(magic_num, str_buf); magic_num[strlen(magic_num)-1]='\0'; /* \nを除く */ if(strcmp(magic_num, "P6") != 0) { fprintf(stderr, "ERROR: magic number(%s) not match.\n", magic_num) ; exit(1) ; } /* 画像の幅(列数)と高さ(行数) */ count_limit=0; sprintf(str_buf,"#"); while((str_buf[0]=='#') || (str_buf[0]=='\n') || (str_buf[0]=='\t') || (str_buf[0]==' ')) { fgets(str_buf,1024,fp); count_limit++; if(count_limit > 1000) { fprintf(stderr,"ERROR: Irregal file format.\n"); exit(1); } } sscanf(str_buf,"%d %d",max_retu,max_gyou); /* 最大値 */ count_limit=0; sprintf(str_buf,"#"); while((str_buf[0]=='#') || (str_buf[0]=='\n') || (str_buf[0]=='\t') || (str_buf[0]==' ')) { fgets(str_buf,1024,fp); count_limit++; if(count_limit > 1000) { fprintf(stderr,"ERROR: Irregal file format.\n"); exit(1); } } sscanf(str_buf,"%d",&max_val); if(max_val > 255) { fprintf(stderr, "ERROR: Irregal max value.\n"); exit(1) ; } /* 画像読み込み */ fread((UCHAR *)&data_buf[0][0][0], sizeof(UCHAR), (*max_retu)*(*max_gyou)*3, fp); /* ファイルを閉じる */ fclose(fp); } /* 動的確保されたCSQ形式の画像メモリからppmフォーマットの画像ファイルを作成 */ void write_ppm_csq_mem(UCHAR ***data_buf,char *fname,int width,int height) { FILE *fp; int m, n; if((fp = fopen(fname, "wb")) == NULL) { fprintf(stderr, "file(%s) can't open\n", fname) ; exit(1) ; } fprintf(fp, "P6\n") ; /* カラー画像かつバイナリーデータの記号 */ // fprintf(fp, "#\t%s\n", fname) ; /* #で始まるのはコメント行 */ fprintf(fp, "%d %d\n", width, height) ; /* 画像の幅(列数)と高さ(行数) */ fprintf(fp, "255\n") ; /* 最大値 */ for(m=0;m<height;m++) for(n=0;n<width;n++) { fwrite(&data_buf[0][m][n], sizeof(UCHAR), 1, fp); fwrite(&data_buf[1][m][n], sizeof(UCHAR), 1, fp); fwrite(&data_buf[2][m][n], sizeof(UCHAR), 1, fp); } fclose(fp) ; } /* 動的確保されたCIP形式の画像メモリからppmフォーマットの画像ファイルを作成 */ void write_ppm_cip_mem(UCHAR ***data_buf,char *fname,int width,int height) { FILE *fp; if((fp = fopen(fname, "wb")) == NULL) { fprintf(stderr, "file(%s) can't open\n", fname) ; exit(1) ; } fprintf(fp, "P6\n") ; /* カラー画像かつバイナリーデータの記号 */ // fprintf(fp, "#\t%s\n", fname) ; /* #で始まるのはコメント行 */ fprintf(fp, "%d %d\n", width, height) ; /* 画像の幅(列数)と高さ(行数) */ fprintf(fp, "255\n") ; /* 最大値 */ fwrite(&data_buf[0][0][0], sizeof(UCHAR), width*height*3, fp); fclose(fp) ; } /* 3次元配列の動的生成 */ UCHAR ***malloc3Duchar(int dim1,int dim2,int dim3) { int i,j; UCHAR ***c1,**c2,*c3; if((c1 = (UCHAR ***)malloc(dim1*sizeof(UCHAR **))) == NULL) error1("can't allocate in malloc3Duchar"); if((c2 = (UCHAR **)malloc(dim1*dim2*sizeof(UCHAR *))) == NULL) error1("can't allocate in malloc3Duchar"); for(i=0;i<dim1;i++) c1[i]=c2+dim2*i; if((c3 = (UCHAR *)malloc(dim1*dim2*dim3*sizeof(UCHAR))) == NULL) error1("can't allocate in malloc3Duchar"); for(i=0;i<dim1;i++) for(j=0;j<dim2;j++) c1[i][j]=c3+(dim2*i+j)*dim3; return c1; } /* 3次元配列の解放 */ void free3Duchar(UCHAR ***point) { free(point[0][0]); free(point[0]); free(point); } /* エラー処理 */ void error1(char *message) { printf("%s\n",message); exit(1); }