実現したいこと
セグメテーションエラーが特定の条件で出る原因を教えて欲しい
前提
並列化に関する課題です。完全に手詰まりしてます。
C
1#include <stdio.h>2#include <stdlib.h>3 4#define SIZE 10245#define PRINT_SIZE 86 7// matrix[row][col]8int a[SIZE][SIZE], b[SIZE][SIZE], c[SIZE][SIZE];9 10void init_a(int mat[SIZE][SIZE]){11 int row, col;12 for (row = 0 ; row < SIZE ; row++){13 for (col = 0 ; col < SIZE ; col++){14 mat[row][col] = row+1;15 }16 }17}18void init_b(int mat[SIZE][SIZE]){19 int row, col;20 for (row = 0 ; row < SIZE ; row++){21 for (col = 0 ; col < SIZE ; col++){22 mat[row][col] = row+col+1;23 }24 }25}26 27void print_matrix_sub(int mat[SIZE][SIZE], int size, int abbr, int start_row){28 int row, col;29 30 for (row = start_row ; row < start_row+size ; row++){31 for (col = 0 ; col < size ; col++){32 printf("%4d ", mat[row][col]);33 }34 if (abbr){35 printf(" ... ");36 for (col = SIZE-size ; col < SIZE ; col++){37 printf("%4d ", mat[row][col]);38 }39 40 }41 printf("\n");42 }43}44 45void print_matrix(int mat[SIZE][SIZE]){46 int size, abbr;47 48 if (SIZE > PRINT_SIZE){49 size = PRINT_SIZE/2;50 abbr = 1;51 }52 else {53 size = SIZE;54 abbr = 0;55 }56 57 print_matrix_sub(mat, size, abbr, 0);58 if (abbr){59 printf(" ...\n");60 print_matrix_sub(mat, size, abbr, SIZE-size);61 }62}63 64void matmul(int a[SIZE][SIZE], int b[SIZE][SIZE], int c[SIZE][SIZE]){65 int row, col, k, s;66 for (row = 0 ; row < SIZE ; row++){67 for (col = 0 ; col < SIZE ; col++){68 s = 0;69 for (k = 0 ; k < SIZE ; k++){70 s += a[row][k]*b[k][col];71 }72 c[row][col] = s;73 }74 }75}76 77int main(void){78 init_a(a);79 init_b(b);80 printf("A\n");81 print_matrix(a);82 printf("\nB\n");83 print_matrix(b);84 85 matmul(a, b, c);86 printf("\nC=AB\n");87 print_matrix(c);88 return 0;89}
SIZE×SIZEのある規則に則って生成された行列A、Bに対してC=ABを求めるコードです。このコードはベースとなるもので、SIZEに定義する数字以外は手を加えません。このコードをpthread.hを用いて並列化する課題です。元のコードをベースに自分で書いたものが以下です。
gdbの結果受け修正したものをさらに下のトピックに載せます。
C
1#include <stdio.h>2#include <stdlib.h>3#include<pthread.h>4 5#define SIZE 10246#define PRINT_SIZE 87#define THREAD_NUM 2 //分割する数8 9#include <pthread.h>10typedef struct {11int start, end, ans[SIZE][SIZE];12} arg_t;//並列化に関わる構造体13 14 15// matrix[row][col]16int a[SIZE][SIZE], b[SIZE][SIZE], c[SIZE][SIZE];17 18 19//Aの生成を分割できるように変更20void init_a(int mat[SIZE][SIZE],int R_start,int R_end){21 int row, col;22 for (row = R_start ; row < R_end ; row++){23 for (col = 0 ; col < SIZE ; col++){24 mat[row][col] = row+1;25 }26 }27}28void init_b(int mat[SIZE][SIZE]){29 int row, col;30 for (row = 0 ; row < SIZE ; row++){31 for (col = 0 ; col < SIZE ; col++){32 mat[row][col] = row+col+1;33 }34 }35}36 37void print_matrix_sub(int mat[SIZE][SIZE], int size, int abbr, int start_row){38 int row, col;39 40 for (row = start_row ; row < start_row+size ; row++){41 for (col = 0 ; col < size ; col++){42 printf("%4d ", mat[row][col]);43 }44 if (abbr){45 printf(" ... ");46 for (col = SIZE-size ; col < SIZE ; col++){47 printf("%4d ", mat[row][col]);48 }49 50 }51 printf("\n");52 }53}54 55void print_matrix(int mat[SIZE][SIZE]){56 int size, abbr;57 58 if (SIZE > PRINT_SIZE){59 size = PRINT_SIZE/2;60 abbr = 1;61 }62 else {63 size = SIZE;64 abbr = 0;65 }66 67 print_matrix_sub(mat, size, abbr, 0);68 if (abbr){69 printf(" ...\n");70 print_matrix_sub(mat, size, abbr, SIZE-size);71 }72}73 74//不要な部分は計算しない。75void matmul(int a[SIZE][SIZE], int b[SIZE][SIZE], int c[SIZE][SIZE],int start,int end){76 int row, col, k, s;77 for (row = start ; row < end ; row++){78 for (col = 0 ; col < SIZE ; col++){79 s = 0;80 for (k = 0 ; k < SIZE ; k++){81 s += a[row][k]*b[k][col];82 }83 c[row][col] = s;84 }85 }86}87 88//最後にスレッド合流後にcに格納するために追加。89void Assmat(int vessel[SIZE][SIZE],int element[SIZE][SIZE],int start,int end){90 int row,col;91 for (row = start ; row < end ; row++){92 for (col = 0 ; col < SIZE ; col++){93 vessel[row][col] = element[row][col];94 }95 }96 97}98 99//スレッドで動かす関数100void *f(void *varg){101 int tmp_a[SIZE][SIZE],tmp_b[SIZE][SIZE];102 arg_t *arg = (arg_t *)varg;103 init_a(tmp_a,arg->start,arg->end);104 init_b(tmp_b); 105 matmul(tmp_a,tmp_b,arg->ans,arg->start,arg->end);106 return NULL;107}108 109 110int main(void){111 int i;112 init_a(a,0,SIZE);113 init_b(b);114 printf("A\n");115 print_matrix(a);116 printf("\nB\n");117 print_matrix(b);118 pthread_t th[THREAD_NUM];119 arg_t arg[THREAD_NUM];120 for(i = 0;i < THREAD_NUM;i++){121 arg[i].start = i*(SIZE/THREAD_NUM);122 arg[i].end = (i+1)*(SIZE/THREAD_NUM);123 //printf("%d to %d\n",arg[i].start,arg[i].end);//デバッグ用の出力124 pthread_create(&th[i],NULL,f,&arg[i]);125 }126 for(i = 0; i<THREAD_NUM; i++){127 pthread_join(th[i],NULL);128 Assmat(c,arg[i].ans,arg[i].start,arg[i].end);129 }130 printf("\nC = AB\n");131 print_matrix(c);132 return 0;133}134
SIZEやTHREAD_NUMを調整し、元のコードとの実行時間の違いを取るのが最終目標になります。
ggc -Wall -lpthreadでのコンパイルは通過してます。ただSIZEを大きくするとセグメンテーションエラーが出ます。具体的に境界値を探せていませんが、500程度なら出力でき、1000はセグメ出ます。元のコードは1024でも出力可能です。
セグメテーションエラーの原因を教えて頂きたいです。
自力でできなかった理由(コメントのおかげで解決しました!)
gdbを使って自力での特定を試みたのですが-gでコンパイルしてもディレクトリにcoreファイルが見つからない→そもそもコアダンプがでない(ただSegmentation faultのみ表示)→ulimitのコマンドが見つからないと言われるといった状態でこっちも手詰まりです…。セグメの原因追及と同時に、こちらも色々調べてる最中です。
gdbの結果受け修正
(gdb) frame 0
#0 0x0000000000400a49 in main () at matmul-th.c:108
108 init_a(a,0,SIZE);
けっきょく何がダメなのからず。ただinit_aは仕様変更する必要無いことに気づき、元のコードのものをそのまま使用。合わせて一部変更
C
1#include <stdio.h>2#include <stdlib.h>3#include<pthread.h>4 5#define SIZE 10006#define PRINT_SIZE 87#define THREAD_NUM 48 9#include <pthread.h>10typedef struct {11int start, end, ans[SIZE][SIZE];12} arg_t;13 14 15// matrix[row][col]16int a[SIZE][SIZE], b[SIZE][SIZE], c[SIZE][SIZE];17 18//分割なし。aを一個だけ生成して範囲指定して使う。19void init_a(int mat[SIZE][SIZE]){20 int row, col;21 for (row = 0 ; row < SIZE ; row++){22 for (col = 0 ; col < SIZE ; col++){23 mat[row][col] = row+1;24 }25 }26}27void init_b(int mat[SIZE][SIZE]){28 int row, col;29 for (row = 0 ; row < SIZE ; row++){30 for (col = 0 ; col < SIZE ; col++){31 mat[row][col] = row+col+1;32 }33 }34}35 36void print_matrix_sub(int mat[SIZE][SIZE], int size, int abbr, int start_row){37 int row, col;38 39 for (row = start_row ; row < start_row+size ; row++){40 for (col = 0 ; col < size ; col++){41 printf("%4d ", mat[row][col]);42 }43 if (abbr){44 printf(" ... ");45 for (col = SIZE-size ; col < SIZE ; col++){46 printf("%4d ", mat[row][col]);47 }48 49 }50 printf("\n");51 }52}53 54void print_matrix(int mat[SIZE][SIZE]){55 int size, abbr;56 57 if (SIZE > PRINT_SIZE){58 size = PRINT_SIZE/2;59 abbr = 1;60 }61 else {62 size = SIZE;63 abbr = 0;64 }65 66 print_matrix_sub(mat, size, abbr, 0);67 if (abbr){68 printf(" ...\n");69 print_matrix_sub(mat, size, abbr, SIZE-size);70 }71}72 73void matmul(int a[SIZE][SIZE], int b[SIZE][SIZE], int c[SIZE][SIZE],int start,int end){74 int row, col, k, s;75 for (row = start ; row < end ; row++){76 for (col = 0 ; col < SIZE ; col++){77 s = 0;78 for (k = 0 ; k < SIZE ; k++){79 s += a[row][k]*b[k][col];80 }81 c[row][col] = s;82 }83 }84}85 86void Assmat(int vessel[SIZE][SIZE],int element[][SIZE],int start,int end){87 int row,col;88 for (row = start ; row < end ; row++){89 for (col = 0 ; col < SIZE ; col++){90 vessel[row][col] = element[row][col];91 }92 }93 94}95 96void *f(void *varg){97 arg_t *arg = (arg_t *)varg;98 //tmpは不要になったので削除99 matmul(a,b,arg->ans,arg->start,arg->end);100 return NULL;101}102 103int main(void){104 int i;105 init_a(a);106 init_b(b);107 printf("A\n");108 print_matrix(a);109 printf("\nB\n");110 print_matrix(b);111 pthread_t th[THREAD_NUM];112 arg_t arg[THREAD_NUM];113 for(i = 0;i < THREAD_NUM;i++){114 arg[i].start = i*(SIZE/THREAD_NUM);115 arg[i].end = (i+1)*(SIZE/THREAD_NUM);116 //printf("%d to %d\n",arg[i].start,arg[i].end);117 pthread_create(&th[i],NULL,f,&arg[i]);118 }119 for(i = 0; i<THREAD_NUM; i++){120 pthread_join(th[i],NULL);121 Assmat(c,arg[i].ans,arg[i].start,arg[i].end);122 }123 printf("\nC = AB\n");124 print_matrix(c);125 return 0;126}
ただし状況変わらずです…。SIZEが大きいとセグメですし、やっぱりinit_a(a)が原因だと言われます。元のコードが大丈夫なのもよく分からないです…。
補足情報(FW/ツールのバージョンなど)
OSはlinuxです。ただ学校配布の物をそのまま使ってるので詳しい環境設定は分かりません。

0 コメント