1

背景情報:私は、いくつかの異なるファイル(ソースでは2つ)を検索して最大の素数を検索できるCプログラムを作成しようとしています。プログラムは、プロセスを高速化するためにマルチスレッド化されています。このプログラムでは、すべてのスレッドがglobalLargestPrimeを割り当てるまでスレッドを待機させることで、時間を無駄にするのではなく、計算時間を優先しています。

問題:私のプログラムのどこかで、IDがパラメーターとして適切に渡されていないか、どこかで私のプログラムがスレッドの1つを飢えさせていると思います。

奇妙な部分:プログラムを実行すると、プログラムは実行されて終了しますが、1つのスレッドしか生成されない場合があるため、両方のテキストファイルを検索しません。また、両方のスレッドを生成し、両方のテキストファイルから読み取る場合もあります

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <pthread.h>
#include <time.h>

pthread_mutex_t mutex;
pthread_cond_t monitor[2];
int globalLargestPrime = 0;
const int numThreads = 2;
FILE *fIN[2];

typedef enum{
  FREE,
  IN_USE
}lrgstPrm;
lrgstPrm monLargestPrime;//create struct

int timed(){
 return time(NULL);
}

int ChkPrim(int n){
  int i;
  int isPrime = 0;
  int root = sqrt(n);
  for(i=2; i<root; i++){
        if(n % i == 0)
          isPrime = 1;
        else
          isPrime = 0;
     }
  return isPrime;
}

void *calc_sqrt(void *threadID){//Create Threads
  int index, currentNum;
  int localLargestPrime = 0;
  int id = *(int *)threadID;
  int thousandsOfTimes = 0;
  //FILE *fIN = fopen("data.txt", "r");

  //printf(PTHREAD_MUTEX_ERRORCHECK);
  //Calculate some sqrts
  while(!feof(fIN[id])){
  for(index = 0; index < 1000; index++ )
  {//Check every thousand times
    fscanf(fIN[id], "%d\n", &currentNum);
    if(currentNum>localLargestPrime)
      if(ChkPrim(currentNum) == 1)
        localLargestPrime = currentNum;
  }

    pthread_mutex_lock(&mutex);

    thousandsOfTimes++;

    while(monLargestPrime == IN_USE)
    pthread_cond_wait(&monitor[id], &mutex);//wait untill mutex is unlocked
    monLargestPrime = IN_USE;
    //Critical Zone
    printf("Entering Critical Zone My ID: %d\n",id);
    if(localLargestPrime > globalLargestPrime)//Check for largest num
      globalLargestPrime = localLargestPrime;
    else
      localLargestPrime = globalLargestPrime;

    for(index = 0; index < numThreads; index++)
      if(index != id)
        pthread_cond_signal(&monitor[id]);//signal all threads that mutex is unlocked
    monLargestPrime = FREE;
    printf("Exiting Critical Zone My ID: %d\n",id);
    pthread_mutex_unlock(&mutex);
 //   printf("done searching thousand times %d My ID: %d\n",thousandsOfTimes, id);
  }
}

void createText(){
  FILE *fOUT = fopen("data.txt", "w");
  int i;
  srand(time(NULL));
  for(i=0; i<10000; i++)
  fprintf(fOUT, "%d\n",rand()%5000);
  fclose(fOUT);
}


int main(){
   printf("This is before creating threads\n");
  int index, timeDiff;
  pthread_t threads[2];
  pthread_mutex_init(&mutex, NULL);
  for(index = 0; index < numThreads; index++)
    pthread_cond_init(&monitor[index], NULL);
  fIN[0] = fopen("data0.txt","r");
  fIN[1] = fopen("data1.txt","r");

  timeDiff = time(NULL);
  //createText();

  for(index = 0; index < numThreads; index++){
    //int *id = malloc(1);
    //*id = index;
    pthread_create(&threads[index],NULL,calc_sqrt,&index);
  }
  for(index = 0; index < numThreads; index++)
    pthread_join(threads[index],NULL);
  printf("This is after creating threads");

  timeDiff = timed() - timeDiff;

  /*Destroy the mutexes & conditional signals*/
  pthread_mutex_destroy(&mutex);
  pthread_cond_destroy(&monitor[0]);
  pthread_cond_destroy(&monitor[1]);


printf("This is the Time %d\n", timeDiff);
printf("This is the Largest Prime Number: %d", globalLargestPrime);
return 0;
}

誰かが私に問題についての洞察を与えてくれたら、それはありがたいです

ありがとう

4

2 に答える 2

3

同じローカル変数のアドレスをスレッドに渡します。変数は各スレッドが作成されるたびに更新されるため、スレッドが開始すると、別のスレッドを対象とした値が読み取られる可能性があります。

pthread_create(&threads[index],NULL,calc_sqrt,&index)
                                              ^^^^^^

最終的には、同じを使用して複数のスレッドを読み取ることになりFILE*ます。

単純なintを渡すので、スレッドパラメータとして値を直接渡すことができます。

pthread_create(&threads[index],NULL,calc_sqrt,(void*)index)

次に、スレッドで次のような値を取得します。

int id = (int)threadID;

コードに条件変数はまったく必要ありません(ただし、問題が発生しているのかどうかはわかりません)。条件変数globalLargestPrimeは、別のスレッドによって使用されているかどうかを追跡します。偶然にも、ミューテックスは同じことをします!試す:

pthread_mutex_lock(&mutex);

thousandsOfTimes++;     // not sure why this local variable even exists, 
                        //  much less is in a critical section

//Critical Zone
printf("Entering Critical Zone My ID: %d\n",id);
if(localLargestPrime > globalLargestPrime)//Check for largest num
  globalLargestPrime = localLargestPrime;
else
  localLargestPrime = globalLargestPrime;   // again, not sure why this is here...

printf("Exiting Critical Zone My ID: %d\n",id);
pthread_mutex_unlock(&mutex);

また、コードはEOFファイルを読み取る前にチェックするアンチパターンを使用します。

while (!feof(somefile)) {
    // whatever...
}

これは間違っていますが、この場合は無害なエラーである可能性があります。見る:

于 2012-12-02T18:54:17.120 に答える
1

手始めに、1バイトだけをmallocし、それをint*に割り当てます。sizeof(int)をmallocする必要があります。

また、各スレッドが独自のファイルで最大の素数を見つけ、各スレッドが終了したら、それらの結果の最大値を取得する方がはるかに簡単です。この方法でスレッド間の同期を必要とする意味はありません。

于 2012-12-02T18:45:03.647 に答える