LINUX.ORG.RU

История изменений

Исправление AndreyKl, (текущая версия) :

#include <iostream>
#include <vector>
#include <iomanip>
#include <thread>
#include "tbb/concurrent_queue.h"

#define THREADS_CNT 10

using namespace std;
using namespace tbb;


class CSimpleNumbers {
	private:
		concurrent_queue<int> queue;
		bool working = true;
public:
	vector<unsigned char> numbers; // Array starts with 3 and has a step of 2: 3, 5, 7, 9 ...

	inline uint NumberToIndex(const uint number) {return (number-3)/2;}; // TODO: number should not be < 3
	inline uint IndexToNumber(const uint index) {return index*2+3;};
	void MarkNonSimple(const uint v,const uint max);
	void consumer(const uint me, const uint max); //worker
public:
	void Initiate(const uint max=6); // Marking with multithreading
	void Print();
	bool IsSimple(uint number);
};

bool CSimpleNumbers::IsSimple(uint number)
{
	uint i;

	if ( number<4 )
		return true;

	if ( number % 2 == 0 )
		return false;

	for (i=0; i<NumberToIndex(number); i++)
		if ( ( numbers[i] == 1 ) && ( number % IndexToNumber(i) == 0 ) )
		  return false;
	
	return true;
};

void CSimpleNumbers::MarkNonSimple(const uint v,const uint max)
{
  uint n = v*3;
  while (n <= max) {
    numbers[NumberToIndex(n)] = 0;
    n += v*2;
  }
};

void CSimpleNumbers::Print()
{
	uint n = 3;
	for (auto i : numbers) {
		if (i == 1)
		  cout << n << " ";
		n += 2;
	}
	cout << endl;
};

void CSimpleNumbers::Initiate(const uint max)
{
  numbers.assign(NumberToIndex(max) + 1, 1);

	vector<thread> threads;

	for(uint i = 0; i < THREADS_CNT; i++) {
		threads.push_back( thread(&CSimpleNumbers::consumer, this, i, max) );
	}

  for (uint head=3;head<=max;head+=2) {
    if ( numbers[NumberToIndex(head)] == 1 ) // Is simple/unchecked yet
      queue.push(head);
  }

	while(!queue.empty())
		std::this_thread::sleep_for(std::chrono::milliseconds(250));

	working = false;

	for(auto& t : threads)
		t.join();
};

void CSimpleNumbers::consumer(const uint me, const uint max) {
	while(working) {
		int n;
		if(!queue.empty()) {
			if(queue.try_pop(n)) {
				if ( ! IsSimple(n) ) { // Is not simple
		      numbers[NumberToIndex(n)] = 0;
		    } else { // Is simple
		      MarkNonSimple(n, max);
		    }
			}
		} else { //queue.empty()
			std::this_thread::sleep_for(std::chrono::milliseconds(10));
		}
	}
}

int main() {
  CSimpleNumbers s;
  s.Print();
  s.Initiate(150000);
  s.Print();
  return 0;
}


конпеляем
g++ -I/home/myname/tmp/tbb41_20130314oss/includes -std=c++11 testqueue.cpp -o testqueue -L/home/myname/tmp/tbb41_20130314oss/build/linux_intel64_gcc_cc4.7_libc2.15_kernel3.5.0_release/ -ltbb

запускаем
LD_PRELOAD=/home/myname/tmp/tbb41_20130314oss/build/linux_intel64_gcc_cc4.7_libc2.15_kernel3.5.0_release/libtbb.so.2 ./testqueue

не пиши через жопу, пиши номрально. и всё будет работать. (hint: у тебя через жопу, у меня нормально).

твой код буду глядеть завтра. но чует моё сердце там банально выполняется работа только внутри IsSimple. поглядим.

Исходная версия AndreyKl, :

#include <iostream>
#include <vector>
#include <iomanip>
#include <thread>
#include "tbb/concurrent_queue.h"

#define THREADS_CNT 10

using namespace std;
using namespace tbb;


class CSimpleNumbers {
	private:
		concurrent_queue<int> queue;
		bool working = true;
public:
	vector<unsigned char> numbers; // Array starts with 3 and has a step of 2: 3, 5, 7, 9 ...

	inline uint NumberToIndex(const uint number) {return (number-3)/2;}; // TODO: number should not be < 3
	inline uint IndexToNumber(const uint index) {return index*2+3;};
	void MarkNonSimple(const uint v,const uint max);
	void consumer(const uint me, const uint max); //worker
public:
	void Initiate(const uint max=6); // Marking with multithreading
	void Print();
	bool IsSimple(uint number);
};

bool CSimpleNumbers::IsSimple(uint number)
{
	uint i;

	if ( number<4 )
		return true;

	if ( number % 2 == 0 )
		return false;

	for (i=0; i<NumberToIndex(number); i++)
		if ( ( numbers[i] == 1 ) && ( number % IndexToNumber(i) == 0 ) )
		  return false;
	
	return true;
};

void CSimpleNumbers::MarkNonSimple(const uint v,const uint max)
{
  uint n = v*3;
  while (n <= max) {
    numbers[NumberToIndex(n)] = 0;
    n += v*2;
  }
};

void CSimpleNumbers::Print()
{
	uint n = 3;
	for (auto i : numbers) {
		if (i == 1)
		  cout << n << " ";
		n += 2;
	}
	cout << endl;
};

void CSimpleNumbers::Initiate(const uint max)
{
  numbers.assign(NumberToIndex(max) + 1, 1);

	vector<thread> threads;

	for(uint i = 0; i < THREADS_CNT; i++) {
		threads.push_back( thread(&CSimpleNumbers::consumer, this, i, max) );
	}

  for (uint head=3;head<=max;head+=2) {
    if ( numbers[NumberToIndex(head)] == 1 ) // Is simple/unchecked yet
      queue.push(head);
  }

	while(!queue.empty())
		std::this_thread::sleep_for(std::chrono::milliseconds(250));

	working = false;

	for(auto& t : threads)
		t.join();
};

void CSimpleNumbers::consumer(const uint me, const uint max) {
	while(working) {
		int n;
		if(!queue.empty()) {
			if(queue.try_pop(n)) {
				if ( ! IsSimple(n) ) { // Is not simple
		      numbers[NumberToIndex(n)] = 0;
		    } else { // Is simple
		      MarkNonSimple(n, max);
		    }
			}
		} else { //queue.empty()
			std::this_thread::sleep_for(std::chrono::milliseconds(10));
		}
	}
}

int main() {
  CSimpleNumbers s;
  s.Print();
  s.Initiate(150000);
  s.Print();
  return 0;
}


конпеляем
g++ -I/home/myname/tmp/tbb41_20130314oss/includes -std=c++11 testqueue.cpp -o testqueue -L/home/myname/tmp/tbb41_20130314oss/build/linux_intel64_gcc_cc4.7_libc2.15_kernel3.5.0_release/ -ltbb

запускаем
LD_PRELOAD=/home/myname/tmp/tbb41_20130314oss/build/linux_intel64_gcc_cc4.7_libc2.15_kernel3.5.0_release/libtbb.so.2 ./testqueue

не пиши через жопу, пиши номрально. и всё будет работать. (hint: у тебя через жопу, у меня нормально).