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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C

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

並列処理

複数の計算が同時に実行される手法

Q&A

解決済

1回答

1436閲覧

phreadsの並列化を用いた総和計算

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

並列処理

複数の計算が同時に実行される手法

0グッド

0クリップ

投稿2020/07/10 06:59

前提・実現したいこと

C言語でpthreadsライブラリを用いたプログラムを作成する課題を行っています。
1からN = 100000までの整数の合計を求めて出力する下記のプログラムを並列化するというものです。
元の並列化されていないプログラムが下記の通りです。

c

1#include <stdio.h> 2#include <stdlib.h> 3 4#define N 100000 5 6int count(int start, int end); 7 8int main(void){ 9 int sum = 0; 10 11 sum = count(1, N); 12 printf("sum of 1..%d = %d\n", N, sum); 13 exit(0); 14} 15 16int count(int start, int end){ 17 int i; 18 int sum = 0; 19 20 for (i = start ; i <=end ; i++){ 21 sum += i; 22 } 23 return sum; 24}

計算が正しいと下記のような表示をすることになっています。

c

1$ ./a.out 2sum of 1..100000 = 705082704

並列化したが、うまく動作しないプログラム

ここではスレッドを4つに分けて、1番目は125000、2番目は2500150000、、、としてそれぞれの総和を求め、4つの総和を最後に求め出力するプログラムです。4つ以外でも対応するように、スレッドの本数をMとして、1番目のスレッドは1~N/M, 2番目はN/M+1~2N/M,、、、というように合計を担当する区間を分割することが条件です。
構造体の変数は、startがスレッドの計算する始めの番号、endが計算する終わりの番号、sumが総和の計算結果です。
関数countが計算を行うスレッドです。

c

1#include <stdio.h> 2#include <stdlib.h> 3#include <pthread.h> 4 5#define N 100000 6#define M 4 7 8struct arg_t { 9 int start; 10 int end; 11 int sum; 12}; 13 14// startからendまでの整数を合計して返す 15void *count(void *arg){ 16 int i; 17 struct arg_t *a = (struct arg_t *)arg; 18 19 for (i = a->start ; i <= a->end ; i++){ 20 a->sum += i; 21 } 22 return NULL; 23} 24 25int main(void){ 26 int sum = 0; 27 int i; 28 pthread_t thr[M]; 29 struct arg_t arg[M]; 30 int a = N/M; 31 32 for (i = 0 ; i < M ; i++){ 33 arg[i].start = (i * a) + 1; 34 arg[i].end = (i + 1) * a; 35 pthread_create(&thr[i], NULL, count, (void *)&arg[i]); 36 } 37 38 for (i = 0 ; i < M ; i++){ 39 pthread_join(thr[i], NULL); 40 } 41 sum += arg[i].sum; 42 printf("sum of 1..%d = %d\n", N, sum); 43 exit(0); 44} 45

いまいちpthread_join,pthread_createの意味と挿入のタイミングが分かりません。実行を何度か行っても毎回結果はばらばらで、マイナスになってしまう場合もあり、その理由もわかりません。
並列化に苦手意識があるので、勉強しなおすために投稿させていただきました。よろしくお願いします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

単に、元のコードの凡ミス(?)です。

  • struct arg_t argはauto変数なので、ちゃんと構造体メンバーsumを初期化しなければダメ。
  • スレッド終了後、M(=4)個のスレッドの計算結果を合計するところが違う。

上記2点を修正すれば、ちゃんと動作します。

C

1#include <stdio.h> 2#include <stdlib.h> 3#include <pthread.h> 4 5#define N 100000 6#define M 4 7 8struct arg_t { 9 int start; 10 int end; 11 int sum; 12}; 13 14// startからendまでの整数を合計して返す 15void *count(void *arg){ 16 int i; 17 struct arg_t *a = (struct arg_t *)arg; 18 19 for (i = a->start ; i <= a->end ; i++){ 20 a->sum += i; 21 } 22 return NULL; 23} 24 25int main(void){ 26 int i; 27 pthread_t thr[M]; 28 struct arg_t arg[M]; 29 int a = N/M; 30 31 for (i = 0 ; i < M ; i++){ 32 arg[i].start = (i * a) + 1; 33 arg[i].end = (i + 1) * a; 34 /* ちゃんと0で初期化 */ 35 arg[i].sum = 0; 36 37 pthread_create(&thr[i], NULL, count, (void *)&arg[i]); 38 } 39 40 int sum = 0; 41 for (i = 0 ; i < M ; i++){ 42 pthread_join(thr[i], NULL); 43 44 /* せっかくループになっているのでここで合計 */ 45 sum += arg[i].sum; 46 } 47 48 /* ここで足してもダメ。 49 sum += arg[i].sum; 50 */ 51 printf("sum of 1..%d = %d\n", N, sum); 52 exit(0); 53} 54

実行結果です。何回実行しても正しい結果が出力されます。

sh

1$ gcc -Wall t18.c -lpthread 2$ ./a.out 3sum of 1..100000 = 705082704 4$ ./a.out 5sum of 1..100000 = 705082704 6$ ./a.out 7sum of 1..100000 = 705082704 8$

投稿2020/07/10 07:31

編集2020/07/10 07:39
dodox86

総合スコア9183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/07/10 08:04

並列化でないところにつまづいてしまっていました。丁寧な回答ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問