2016-07-16 3 views
3

Я новичок в концепциях потоков, и я стараюсь их лучше понять. Прочитав теорию, я решил написать простую программу с потоками. Я нашел (может быть простой) задачи в интернете:Как сделать потоки в этом коде для самостоятельного перехода

Напишите программу, которая вычисляет простые числа и числа Fibunacci в разных потоках.

a. Первый поток начинает поиск простого числа от 1 до убийства программы и когда найдено простое число, программа должна указать время для поиска этого номера.

b. Второй поток вычисляет и печатает числа Fibunacci от 1 до убийства программы. Когда новый номер Fibunacci составляет , программа распечатывает это число и время для расчета этого номера .

c. Время отображается в мс (миллисекундах)

d. Подумайте о стратегиях отсутствия перекрытия сообщений с консоли .

e. Программа должна работать с большими возможными числами. Когда номер слишком велик, чтобы удерживаться в таком виде, как unsigned long long, программа останавливает вычисление такого рода номеров и показывает сообщение об ошибке .

Пример вывода:

Прайм 1, 0,1 мс.

Fibunacci 1, 0,1 мс.

Prime 2, 0.1 ms.

Fibunacci 2, 0,1 мс.

Прайм 3, 0,1 мс.

Fibunacci 3, 0,1 мс.

Fibunacci 5, 0,1 мс.

Prime 5, 0,1 мс.

Fibunacci 8, 0,1 мс.

Prime 7, 0.1 ms.

Fibunacci 13, 0.2 ms.

Fibbunaci 21, 0,1 мс.

Prime 11, 0.2 ms.

Это код, который я написал:

#include <iostream> // std::cout 
#include <string> // std::cout << std::string 
#include <thread> // std::thread 
#include <time.h> // clock() 
#include <mutex> // std::mutex 

std::mutex mtx; 
int timePrim, timeFib; 

bool isPrime(int testedNumber) 
{ 
    if (testedNumber <= 2) return true; 
    if (testedNumber % 2 == 0) return false; 
    for (int i = 3; (i*i) <= testedNumber; i += 2) 
    { 
     if (testedNumber % i == 0) return false; 
    } 
    return true; 
} 

// the function is realized by a recursive algorithm; credits to stackoverflow ;) 
bool isFibonacci(unsigned long long testedNumber, int a = 1, int b = 1) 
{ 
    if (testedNumber == 0 || testedNumber == 1) 
     return true;//returning true for 0 and 1 right away. 
    int nextFib = a + b;//getting the next number in the sequence 
    if (nextFib > testedNumber) 
     return false;//if we have passed the tested number, it's not in the sequence 
    else if (nextFib == testedNumber) 
     return true;//if we have a perfect match, the tested number is in the sequence 
    else 
     isFibonacci(testedNumber, b, nextFib);//otherwise, get the next fibonacci number and repeat. 
} 

void CheckNumber(unsigned long long numberToCheck, bool ifPrime) 
{ 
    bool result = false; 
    if (ifPrime == true) 
    { 
     result = isPrime(numberToCheck); 
    } 
    else 
    { 
     result = isFibonacci(numberToCheck); 
    } 
    if (result == true) 
    { 
     float currentTime = 0; 
     std::string typeNumber = ""; 
     if (ifPrime == true) 
     { 
      typeNumber = "Prime"; 
      currentTime = (float)(clock() - timePrim)/CLOCKS_PER_SEC; 
      timePrim = clock(); 
     } 
     else 
     { 
      typeNumber = "Fibonacci"; 
      currentTime = (float)(clock() - timeFib)/CLOCKS_PER_SEC; 
      timeFib = clock(); 
     } 
     mtx.lock(); 
     std::cout << typeNumber << " number " << numberToCheck << "; time " << currentTime << std::endl; 
     mtx.unlock(); 
    } 
} 

int main() 
{ 
    timePrim = timeFib = clock(); 

    for (unsigned long long i = 0; true; i++) // endless for loop == while(true) // by requirements 
    { 
     std::thread primeThread = std::thread(CheckNumber, i, true); 
     std::thread fibThread = std::thread(CheckNumber, i, false); 
     primeThread.join(); 
     fibThread.join(); 
    } 

} 

Насколько я понимаю, эти две нити должны идти независимо друг другу и печатать результаты, как быстро соответствующая функция поиска номера. Но результаты выглядят просто - по порядку продвижения итератора в цикле for в основной функции, но не ко времени вычисления. Это фрагмент сообщения с консоли:

Prime number 0; время 0.005

Число Фибоначчи 0; время 0,007

№ первичного заказа; время 0,03

Fibonacci номер 1; время 0.029

Prime number 2; время 0,093

Fibonacci номер 2; время 0.092

Prime number 3; время 0.023

Fibonacci номер 3; время 0.023

Prime number 5; время 0,05

Fibonacci номер 5; время 0.052

Prime number 7; время 0.023

Фибоначчи номер 8; время 0.045

Prime number 11; время 0.038

Простой номер 13; время 0.077

Фибоначчи номер 13; время 0.091

Простой номер 17; время 0,019

Праймер № 19; время 0,179

Фибоначчи номер 21; время 0,208

Prime number 23; время 0.027

Что я должен исправить в этом коде, чтобы сделать независимые потоки? Где моя ошибка/s?

// извините, если текст на английском языке выше плохо - это не мой родной язык, так что возможно, я сделал некоторые ошибки ...

+0

Сколько потоков вы намерены иметь? 2, 3 или бесконечно? – nwp

+0

join() ждет завершения потока, поэтому каждый раз цикл цикла сериализуется –

ответ

1

Теперь ваша программа создает темы для каждого номера i, поэтому, если вы вычислите простые числа и фибоначчи, где i - от 0 до gazilion, то создаст и уничтожит потоки 2 gazilions.Для создания темы требуются системные вызовы, и это не так быстро делать в цикле.

Также вы делаете оба потока ожидающими друг друга, прежде чем отправлять больше работы.

Вот как ваша программа выглядит в псевдокоде (любое сходство с реальными языками программирования является чисто случайным):

def prime(i): 
    calculate one prime 

def fibo(i): 
    calculate one fibo 

for i from 0 to gazilion: 
    prime_thread = create_and_run_thread(prime, i) # expensive, runs gazilion times 
    fibo_thread = create_and_run_thread(fibo, i) # expensive, runs gazilion times 

    wait_for(prime_thread)  # wait until single number is crunched 
    wait_for(fibo_thread)  # wait until single number is crunched 

    destroy_thread(prime_thread)     
    destroy_thread(fibo_thread)     

Вместо этого, вы можете создать 2 постоянных потоков на задачи и петли отдельно:

def prime(): 
    for i from 0 to gazilion: 
     calculate one prime 

def fibo(): 
    for i from 0 to gazilion: 
     calculate one fibo 


prime_thread = create_and_run_thread(prime) # expensive, but runs only once 
fibo_thread = create_and_run_thread(fibo) # expensive, but runs only once 

wait_for(prime_thread)  # you only wait until gazilion is reached 
wait_for(fibo_thread)  # you only wait until gazilion is reached 

destroy_thread(prime_thread)     # runs oly once 
destroy_thread(fibo_thread)     # runs oly once 
1

Создание двух векторов std::thread объектов. Один для расчетов Фибоначчи, один для вычислений простых чисел. Затем создайте два цикла: один для создания обоих потоков и добавления их к векторам, а затем еще один цикл для присоединения всех потоков в векторах.

Хотя вторая петля ждет выхода первого потока, все потоки, созданные в первом цикле, будут выполняться параллельно.


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

Смежные вопросы