Здравствуйте, я пытаюсь написать многопоточную программу на C ++ с использованием библиотеки потоков POSIX, чтобы найти число простых чисел от 1 до 10 000 000 (10 миллионов) и выяснить, сколько микросекунд требуется ...

Создание моих потоков и их запуск работает совершенно нормально, однако мне кажется, что в моей функции Prime обнаружена ошибка при определении, является ли число простым или нет ...

Я продолжаю получать 78496 в качестве выходных данных, однако я хочу 664579. Ниже приведен мой код. Любые намеки или указатели будут с благодарностью.

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <sys/time.h> //measure the execution time of the computations

using namespace std;

//The number of thread to be generated
#define NUMBER_OF_THREADS 4

void * Prime(void* index);

long numbers[4] = {250000, 500000, 750000, 1000000};
long start_numbers[4] = {1, 250001, 500001, 750001};

int thread_numbers[4] = {0, 1, 2, 3};

int main(){
  pthread_t tid[NUMBER_OF_THREADS];

  int tn;

  long sum = 0;

  timeval start_time, end_time; 

  double start_time_microseconds, end_time_microseconds;

  gettimeofday(&start_time, NULL);

  start_time_microseconds = start_time.tv_sec * 1000000 + start_time.tv_usec;
  for(tn = 0; tn < NUMBER_OF_THREADS; tn++){
    if (pthread_create(&tid[tn], NULL, Prime, (void *) &thread_numbers[tn]) == -1 ) {
        perror("thread fail");
        exit(-1);
    }
  }
 long value[4];

 for(int i = 0; i < NUMBER_OF_THREADS; i++){
    if(pthread_join(tid[i],(void **) &value[i]) == 0){
        sum = sum + value[i]; //add four sums together
    }else{
      perror("Thread join failed");
      exit(-1);
    }
 }
 //get the end time in microseconds
 gettimeofday(&end_time, NULL);

 end_time_microseconds = end_time.tv_sec * 1000000 + end_time.tv_usec;

 //calculate the time passed
 double time_passed = end_time_microseconds - start_time_microseconds;

 cout << "Sum is: " << sum << endl;
 cout << "Running time is: " << time_passed << " microseconds" << endl;

 exit(0);
}


//Prime function
void* Prime(void* index){
  int temp_index;

  temp_index = *((int*)index);
  long  sum_t = 0;

  for(long i = start_numbers[temp_index]; i <= numbers[temp_index]; i++){
        for (int j=2; j*j <= i; j++)
        {
            if (i % j == 0) 
            {
                break;
            }
            else if (j+1 > sqrt(i)) {
                sum_t++;
            }
         }

  }

  cout << "Thread " << temp_index << " terminates" << endl;
  pthread_exit( (void*) sum_t);
}```
0
Spencer Brunnert 19 Фев 2020 в 22:00

2 ответа

Лучший ответ

Это потому, что вы использовали 10 ^ 6 вместо 10 ^ 7.

Также добавлены некоторые угловые корпуса для номеров 1, 2 и 3:

//Prime function
void* Prime(void* index){
  int temp_index;

  temp_index = *((int*)index);
  long  sum_t = 0;

  for(long i = start_numbers[temp_index]; i <= numbers[temp_index]; i++){

      // Corner cases

      if(i<=1)continue;  
      if (i <= 3){
            sum_t++;
            continue;
      }


      for (int j=2; j*j <= i; j++)
      {
          if ((i % j == 0) ||  (i %( j+2))==0 ) 
          {
              break;
          }
          else if (j+1 > sqrt(i)) {
              sum_t++;
          }
       }

  }

    cout << "Thread " << temp_index << " terminates" << endl;
    pthread_exit( (void*) sum_t);
}

Я проверил ваш код с правильным номером и получил правильное количество простых чисел в качестве вывода:

Thread 0 terminates
Thread 1 terminates
Thread 2 terminates
Thread 3 terminates
Sum is: 664579
Running time is: 4.69242e+07 microseconds

Спасибо @chux - восстановите Монику за указание на это

3
Deepak Tatyaji Ahire 19 Фев 2020 в 20:06

Наряду с принятием 10 ^ 7 в качестве чисел, разделенных на потоки, вместо установки предела равным 10 ^ 6, существует ряд других мелких ошибок и может быть сделан ряд оптимизаций -

  1. Прежде всего, стартовые номера могут быть от 2-х

    long start_numbers[4] = {2, 2500001, 5000001, 7500001};

  2. sum_t ++ в вашем коде может не работать в крайних случаях. Лучше следовать следующему алгоритму для вычисления функции Prime

      bool flag = false;
      for(long i = start_numbers[temp_index]; i <= numbers[temp_index]; i++){
      flag = false;
    
      for (long j=2; j*j <= i; j++){
          if (i % j == 0 ) 
          {
              flag = true;
              break;
          }
       }
       if(!flag)
            sum_t++;
      }
    

После этих 2 операций я получаю результат как

Thread 0 terminates
Thread 1 terminates
Thread 2 terminates
Thread 3 terminates
Sum is: 664579
Running time is: 6.62618e+06 microseconds

Редактировать: (Примечание: в этом случае j берется как long тип данных, но он также может работать с int в этом «примере», поскольку протестированный компилятор принимает int как 32 бита длинный)

0
Abhaas Goyal 19 Фев 2020 в 21:04