[英]Find all combinations that add upto given number using parallel threads
The problem is to find a way to reach the same result as already reached in the code below but to use a custom amount of threads, use critical section and semaphore, so to parallelize the below code问题是找到一种方法来达到与下面代码中已经达到的结果相同的结果,但要使用自定义数量的线程,使用临界区和信号量,以便并行化下面的代码
I have tried to parallelize the recursive parts of the code but I didn't come up with any reasonable solution我试图并行化代码的递归部分,但我没有想出任何合理的解决方案
The code somehow could be parallelized here, semaphore can be used to parallelize the code but it's not clear what parts exactly can be run in parallel代码可以在这里以某种方式并行化,信号量可用于并行化代码,但尚不清楚究竟哪些部分可以并行运行
Already running solution:已运行解决方案:
C++ program to find out all combinations of positive numbers that add upto given number C++ 程序找出所有正数的组合加上给定的数字
#include <iostream>
using namespace std;
// arr - array to store the combination
// index - next location in array
// num - given number
// reducedNum - reduced number
void findCombinationsUtil(int arr[], int index,
int num, int reducedNum)
{
// Base condition
if (reducedNum < 0)
return;
// If combination is found, print it
if (reducedNum == 0)
{
for (int i = 0; i < index; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
// Find the previous number stored in arr[]
// It helps in maintaining increasing order
int prev = (index == 0)? 1 : arr[index-1];
// note loop starts from previous number
// i.e. at array location index - 1
for (int k = prev; k <= num ; k++)
{
// next element of array is k
arr[index] = k;
// call recursively with reduced number
findCombinationsUtil(arr, index + 1, num,
reducedNum - k);
}
}
Function to find out all combinations of positive numbers that add upto given number.函数找出加起来为给定数字的所有正数组合。 It uses findCombinationsUtil()它使用 findCombinationsUtil()
void findCombinations(int n)
{
// array to store the combinations
// It can contain max n elements
int arr[n];
//find all combinations
findCombinationsUtil(arr, 0, n, n);
}
Driver code驱动程序代码
int main()
{
int n = 5;
findCombinations(n);
return 0;
}
source: https://www.geeksforgeeks.org/find-all-combinations-that-adds-upto-given-number-2/来源: https : //www.geeksforgeeks.org/find-all-combinations-that-adds-upto-given-number-2/
I'll quote a sentence from another answer:我引用另一个答案中的一句话:
I'll take the advice route.我会走咨询路线。 Before trying to make your program faster using threads, you first want to make it faster in the single threaded case.在尝试使用线程使您的程序更快之前,您首先希望在单线程情况下使其更快。
In your specific problem I think it's somehow hard to parallelize the function.在您的具体问题中,我认为并行化该函数有点困难。 You can, for example, let each thread find the combination of numbers in a sub-array of the original array, but what about the combinations in different sub-arrays?例如,您可以让每个线程在原始数组的子数组中找到数字的组合,但是不同子数组中的组合呢? Clearly, there is a limit for parallelizing this problem, because each number depends on every other number.显然,并行化这个问题是有限制的,因为每个数字都依赖于其他数字。 You can pre-cache sums before doing parallel computing, but if you want the numbers forming the combination it won't help much.您可以在进行并行计算之前预先缓存总和,但是如果您想要形成组合的数字,它不会有太大帮助。
See these links for more information.有关更多信息,请参阅这些链接。
https://www.codeproject.com/Articles/1247260/Cplusplus-Simple-Permutation-and-Combination-Paral https://www.codeproject.com/Articles/1247260/Cplusplus-Simple-Permutation-and-Combination-Paral
Parallelizing recursive function using OpenMP in C++ 在 C++ 中使用 OpenMP 并行化递归函数
Ok, there is a reasonable solution to use one thread per each fixed number of sums, ie for a 5 number sum is 1 thread, for a 4 number sum is another thread, and for a 3 number sum is thread one more.好的,有一个合理的解决方案是为每个固定数量的总和使用一个线程,即对于 5 个数字总和是 1 个线程,对于 4 个数字总和是另一个线程,对于 3 个数字总和是一个线程。 So that we can use our logical cores to handle the calculations!这样我们就可以使用我们的逻辑内核来处理计算了!
I'm not a professional (I do not pretend to be a professional) in this current case, this is NOT the perfect solution but it solves the given task of using parallel threads and it works:在当前的情况下,我不是专业人士(我不假装是专业人士),这不是完美的解决方案,但它解决了使用并行线程的给定任务并且它有效:
#include "stdafx.h"
#include <fstream>
#include <string>
#include <iostream>
#include <vector>
#include <Windows.h>
#include <chrono>
#include <queue>
typedef int ReverseIterator;
//#define SHOW_RESULTS
CRITICAL_SECTION cs;
HANDLE sem;
HANDLE* threads;
//using namespace std;
std::ifstream g_inputStream;
std::ofstream g_outputStream;
int g_threadCount;
int g_countOfCombinations = 0;
int g_targetNumber = 0;
std::string g_millisecondsSpentOutputStr;
namespace Set {
class ContainerSet {
public:
bool _empty;
int _size;
int* _collection;
int _lastIndex;
ContainerSet* next;
ContainerSet()
{
_lastIndex = 0;
_size = 0;
_collection = nullptr;
_empty = true;
}
ContainerSet(const ContainerSet& source)
{
Initialize(source);
}
void Initialize(const ContainerSet& source)
{
_lastIndex = 0;
_size = source._size;
_collection = new int[_size];
for (int i = 0; i < _size; i++) {
_collection[i] = source[i];
}
_empty = false;
}
ContainerSet(int size)
{
_lastIndex = 0;
_collection = new int[size];
_size = size;
_empty = false;
}
~ContainerSet()
{
if (_empty == true)
return;
else {
if (_collection) {
delete _collection;
_collection = nullptr;
_empty = true;
}
}
}
int operator[] (int i) const {
if (_collection == nullptr)
return -1;
return _collection[i];
}
int& operator[](int i) {
if (_collection == nullptr)
return _collection[0];
return _collection[i];
}
bool operator<(const ContainerSet& left)
{
return left._collection < this->_collection;
}
int size() { if (this == nullptr) return 0; return _size; }
bool Equal(ContainerSet* set) {
if (_collection == nullptr || _size < 0 )
return false;
for (int i = 0; i < set->size(); i++)
{
if (set->_collection[i] != this->_collection[i])
return false;
}
if(set->size() == this->size())
return true;
return false;
}
int* rbegin() { return &_collection[_size - 1]; }
int* rend() { return &_collection[0]; }
int* begin() { return &_collection[0]; }
int* end() { return &_collection[_size - 1]; }
};
class DynamicListOfSets {
public:
bool _empty;
ContainerSet* _last;
ContainerSet* _first;
DynamicListOfSets()
{
Initialize(this);
}
static void Initialize(DynamicListOfSets* list) {
list->_first = nullptr;
list->_last = nullptr;
}
ContainerSet* back() {
return _last;
}
bool HasEqualMember(ContainerSet* member)
{
if (_first == nullptr)
{
return false;
}
ContainerSet* current = _first;
do {
//do stuff
if (current->Equal(member))
return true;
current = current->next;
} while (current->next != nullptr);
return false;
}
ContainerSet* front()
{
return _first;
}
void push_back(ContainerSet* set)
{
if (set == nullptr)
return;
set->next = nullptr;
if (_last == nullptr) {
_first = set; _last = set;
} else {
_last->next = set;
_last = set;
}
_empty = false;
}
void clear() {
ContainerSet* current = _first;
if (current == nullptr) {
_empty = true;
return;
}
ContainerSet* next = current->next;
do {
//extract next from current
next = current->next;
//delete current
delete current;
//move next
current = next;
//if next exist
} while (next != nullptr);
_empty = true;
}
void pop_front() {
if (_first != nullptr)
{
auto next = _first->next;
delete _first;
if (next != nullptr)
_first = next;
}
}
~DynamicListOfSets()
{
_empty = true;
}
};
class ListOfSets {
public:
//data fields
ContainerSet** _collection;
int _size;
int _pointer;
ContainerSet* operator[] (int i) const {
if (_collection == nullptr)
return nullptr;
return _collection[i];
}
//constructors
ListOfSets()
{
_size = 0;
_collection = nullptr;
_pointer = -1;
}
ListOfSets(int size)
{
Initialize(this, size);
}
static void Initialize(ListOfSets* list, int size)
{
list->_size = size;
list->_collection = new ContainerSet*[size];
for (int i = 0; i < size; i++)
{
list->_collection[i] = new ContainerSet(size);
}
list->_pointer = -1;
}
//methods
int size()
{
return _size;
}
void push_back(ContainerSet* list)
{
if (!IsFull())
{
if (list == nullptr)
{
//TODO: check and correct here
throw 0;
return;
}
_pointer++;
_collection[_pointer] = list;
}
}
ContainerSet* next(int index)
{
if ( (index+1) >= _size)
return nullptr;
return _collection[index + 1];
}
ContainerSet* front()
{
if(_collection != nullptr)
return _collection[0];
return nullptr;
}
ContainerSet* pop_back()
{
if (!HasValues())
return nullptr;
else {
if(_pointer-1 >= 0)
return _collection[_pointer--];
return false;
}
}
ContainerSet* pop_front()
{
if (!HasValues())
return nullptr;
else {
if (_pointer >= 0)
return _collection[0];
return false;
}
}
bool IsFull()
{
return (_pointer + 1) >= _size;
}
bool HasValues()
{
if (_collection == nullptr || _size <= 0)
return false;
return true;
}
ContainerSet* rbegin()
{
if (_collection == nullptr || _collection[_size - 1] == nullptr)
return nullptr;
return _collection[_size - 1];
}
ContainerSet* rend()
{
if (_collection == nullptr || _collection[0] == nullptr)
return nullptr;
return _collection[0];
}
ContainerSet* begin()
{
if (_collection == nullptr || _collection[0] == nullptr)
return nullptr;
return _collection[0];
}
ContainerSet* end()
{
if (_collection == nullptr || _collection[_size - 1] == nullptr)
return nullptr;
return _collection[_size - 1];
}
void clear()
{
if (_collection == nullptr)
return;
if (_collection[0]) {
for (int cSI = 0; cSI < _size; cSI++)
{
if (_collection[cSI] != nullptr)
{
delete _collection[cSI];
_collection[cSI] = new Set::ContainerSet();
}
}
}
ListOfSets();
}
~ListOfSets() {
clear();
}
};
}
typedef Set::ContainerSet SolutionIntContainer;
namespace SimpleTimer {
class SimpleTimer
{
public:
SimpleTimer::SimpleTimer()
{
start = std::chrono::high_resolution_clock::now();
stopped = false;
}
std::string SimpleTimer::Stop()
{
end = std::chrono::high_resolution_clock::now();
duration = end - start;
float result = duration.count();
std::string strResult;
strResult.append("Time spent: ");
strResult.append(std::to_string(result));
strResult.append("seconds");
strResult.append("\n");
return strResult;
}
std::string SimpleTimer::StopMilliseconds()
{
stopped = true;
end = std::chrono::high_resolution_clock::now();
duration = end - start;
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
std::string strResult;
strResult.append(std::to_string(millis));
return strResult;
}
SimpleTimer::~SimpleTimer()
{
if (stopped)
return;
end = std::chrono::high_resolution_clock::now();
duration = end - start;
float result = duration.count();
std::cout << "Time spent: " << result << " seconds" << std::endl;
}
private:
std::chrono::time_point<std::chrono::steady_clock> start, end;
std::chrono::duration<float> duration;
bool stopped;
};
}
namespace NewSolution {
bool Equal(SolutionIntContainer* left, SolutionIntContainer* right) {
for (int i = 0; i < (left->size() - 1); i++) {
if ((*left)[i] != (*right)[i])
return false;
}
return true;
}
int Difference(int sum) {
return g_targetNumber - sum;
}
int Difference(SolutionIntContainer& targetList) {
int sum = 0;
for (auto it = targetList.rbegin(); it >= targetList.rend(); it--) {
sum += (*it);
}
return Difference(sum);
}
class CombinationStorage {
private:
Set::DynamicListOfSets descendants;
public:
// constructors
CombinationStorage(int size) {
Set::DynamicListOfSets::Initialize(&descendants);
}
// methods
void DeleteDescendants() {
//descendants.clear();
}
bool FindDescendant(SolutionIntContainer* sIC) {
auto it = descendants.front();
while (it != nullptr) {
if (Equal(it, sIC))
return true;
it = it->next;
}
return false;
}
void AddDescendant(SolutionIntContainer* combinationNode) {
if (combinationNode != nullptr)
descendants.push_back(new SolutionIntContainer(*combinationNode));
}
SolutionIntContainer* GetNextDescendant() {
return descendants.front();
}
void DeleteFrontDescendant() {
descendants.pop_front();
}
}; // class CombinationComparator
class ListHandler {
private:
CombinationStorage combinationStorage;
SolutionIntContainer sourceList;
public:
// public fields:
static Set::ListOfSets startingCombinations;
//constructor:
ListHandler(SolutionIntContainer* s, int size) : combinationStorage(size)
{
sourceList.Initialize(*s);
//InitializeCombinations();
}
//methods:
void DeleteInnerDescendants()
{
combinationStorage.DeleteDescendants();
}
void NewDescendantFound(SolutionIntContainer* combination)
{
g_countOfCombinations++;
combinationStorage.AddDescendant(combination);
}
void CombinationFound(SolutionIntContainer* combination) {
g_countOfCombinations++;
}
bool RightIsGreaterOrEqual(int left, int right) {
if (right >= left)
return true;
return false;
}
int IncludingIndexDifference(int sum, int reductionOffset)
{
return ((g_targetNumber - reductionOffset) - sum);
}
//Tested OK 10:47 PM 5/23/2019
bool CheckOrder(SolutionIntContainer& list, int maxIndex)
{
// TODO: optimize
int leftI = 0, rightI = 1;
int sum = list[leftI];
for (; rightI <= maxIndex; leftI++, rightI++) {
if (!RightIsGreaterOrEqual(list[leftI], list[rightI]))
return 1;
sum += list[rightI];
}
int reductionOffset = 0;
for (int i = (rightI + 1); i < list.size(); i++)
{
reductionOffset += list[i];
}
return IncludingIndexDifference(sum, reductionOffset);
}
static void ShowList(SolutionIntContainer& list, std::string* additionalContents = nullptr, bool reversed = false)
{
#ifdef SHOW_RESULTS
if (reversed) {
for (auto i = list.rbegin(); i >= list.rend(); i--)
{
std::cout << (*i) << " ";
}
}
else {
for (auto i = list.begin();
i <= list.end();
i++) {
std::cout << (*i) << " ";
}
}
if (additionalContents != nullptr) {
std::cout << " \t " << *additionalContents << " \t ";
}
std::cout << std::endl;
#endif
}
static void ShowCombination(SolutionIntContainer& container, std::string* additionalContents = nullptr, bool reversed = false) {
#ifdef SHOW_RESULTS
std::cout << g_countOfCombinations << ") \t";
ShowList(container, additionalContents, reversed);
#endif
}
void Inc(SolutionIntContainer& list, int index, int count = 1) {
if (index < 0 || index >= list.size())
return;
list[index] = list[index] + count;
}
void Dec(SolutionIntContainer& list, int index) {
if (index < 0 || index >= list.size())
return;
list[index] = list[index] - 1;
}
void TryDecAndInc(SolutionIntContainer& newList, SolutionIntContainer& oldList, int reductionIndex, int increasingIndex)
{
newList.Initialize(oldList);
Dec(newList, reductionIndex);
Inc(newList, increasingIndex);
}
SolutionIntContainer& TryDecAndInc(SolutionIntContainer& const newList, int reductionIndex, int increasingIndex)
{
Dec(newList, reductionIndex);
Inc(newList, increasingIndex);
return newList;
}
bool RebuildDownstairs(SolutionIntContainer& list, int rightI, int leftI = -1)
{
if (leftI == -1)
leftI = rightI - 1;
SolutionIntContainer newTryList;
TryDecAndInc(newTryList, list, rightI, leftI);
if (CheckOrder(newTryList, rightI) > 0)
return false;
if (!combinationStorage.FindDescendant(&newTryList)) {
NewDescendantFound(&newTryList);
list[rightI] = list[rightI] - 1;
list[leftI] = list[leftI] + 1;
#ifdef SHOW_RESULTS
std::string indexesStr = std::string("rightIndex = ") + std::to_string(rightI) +
+" ; " + std::string("leftIndex = ") + std::to_string(leftI) + std::string(";");
ShowCombination(list
, &indexesStr
);
#endif //SHOW_RESULTS
return true;
}
return false;
}
bool GlidePossible(SolutionIntContainer& sIC)
{
int first = sIC[0];
int last = sIC[sIC.size() - 1];
int offset = 1;
if (last > (first + offset))
{
return true;
}
return false;
}
int startingLeftLeftIndex;
bool glode = false;
int lastRight = 1;
int lastLeft = 1;
bool Exists(SolutionIntContainer& list, int minR, int maxL) {
if (minR == lastRight && maxL == lastLeft)
return true;
return false;
}
void TryGhostGlideALine(SolutionIntContainer& list, int rightIndex, int leftLeftI,
int& depthOverall, int currentDepth)
{
SolutionIntContainer newTryList(list);
while (depthOverall == currentDepth) //(true)
{
if (leftLeftI < 0) {
leftLeftI = startingLeftLeftIndex;
}
if (!GlidePossible(newTryList))
return;
TryDecAndInc(newTryList, rightIndex, leftLeftI);
if (CheckOrder(newTryList, rightIndex) <= 0) {
if (
!combinationStorage.FindDescendant(&newTryList)
) {
NewDescendantFound(&newTryList);
//if(newTryList[rightIndex] < lastRight)
lastRight = newTryList[rightIndex];
//if (newTryList[leftLeftI] > lastLeft)
lastLeft = newTryList[leftLeftI];
ShowCombination(newTryList);
}
TryGhostGlideALine(newTryList, rightIndex, leftLeftI, ++depthOverall, ++currentDepth);
// Repeat recursively
TryGhostGlideALine(newTryList, rightIndex, (leftLeftI - 1),
(depthOverall = currentDepth),
/*++*/currentDepth
);
} else {
return;
}
leftLeftI--;
}
}
void ChangeValue(SolutionIntContainer& container, int index, int value) {
container[index] = value;
}
bool CanDecRightAndIncLeft(SolutionIntContainer& list, int rightI, int leftI) {
return CheckOrder(TryDecAndInc(list, rightI, leftI), rightI) <= 0;
}
bool FindNext(SolutionIntContainer& list, int rightI)
{
bool result = true;
// working with previous
// Find the left Element
// Check if left element is to the left of right
int leftI = (rightI - 1);
// exit if can't shift
// (exit if left doesn't exist)
if (leftI < 0)
return false;
// TODO: exit condition
if (!RebuildDownstairs(list, rightI))
return false;
// a third element we are currently working on
// it is to the third position to the left
// and more if needed
int leftLeftI = (leftI - 1);
if (leftLeftI >= 0)
{
startingLeftLeftIndex = leftLeftI;
int depth = 0;
lastRight = list[rightI];
lastLeft = 1;
//TODO: check if works
combinationStorage.DeleteDescendants();
TryGhostGlideALine(list, rightI, leftLeftI, depth, depth//, 0
);
}
// Ghost Glide OK, continue
return result;
}
// Rebuild saving existing right element
bool RebuildCombination(SolutionIntContainer& list,
ReverseIterator rightIndex)
{
if (rightIndex <= 0)
return false;
// strictly more than 0 because we move towards left border
// and check for the previous (right - 1) element
int orderDisplacement = CheckOrder(list, rightIndex);
if (orderDisplacement < 0)
Inc(list, rightIndex);
if (orderDisplacement > 0)
return false;
int leftI = (rightIndex - 1);
// Find the changed
while (FindNext(list, rightIndex)) {
}
return true;
}
static void InitializeCombinations( int count )
{
Set::ListOfSets::Initialize(&startingCombinations, count-1);
for (int i = count; i > 1; i--)
{
SolutionIntContainer* newList = new SolutionIntContainer(i);
for (int k = 0; k < i; k++) {
(*newList)[k] = 1;
}
startingCombinations.push_back(newList);
}
}
void FindAllSumsFixedLength()
{
ShowList(sourceList);
int rightIndex = /*firstRun ?*/ sourceList.size() - 1 /*: iterator - 1*/;
int left = (rightIndex - 1);
int difference = g_targetNumber;
while ((difference = NewSolution::Difference(sourceList)) > 0) {
sourceList[rightIndex]++;
}
NewDescendantFound(&sourceList);
ShowCombination(sourceList);
while (
RebuildCombination(sourceList, rightIndex)
)
{
--rightIndex;
}
}
static SolutionIntContainer Next()
{
EnterCriticalSection(&::cs);
if (startingCombinations.size() == 0)
return SolutionIntContainer(0);
SolutionIntContainer* sourceList = startingCombinations.pop_front();
LeaveCriticalSection(&::cs);
return *sourceList;
}
static void WriteLineThreadBlocking(const char* line, int length = 0)
{
EnterCriticalSection(&::cs);
std::cout << line << std::endl;
LeaveCriticalSection(&::cs);
}
static DWORD WINAPI FindAllSumsFixedLengthMT(LPVOID pListHandler)
{
ListHandler* pLH = (ListHandler*)pListHandler;
DWORD dwWaitResult;
BOOL bContinue = TRUE;
// Try to enter the semaphore gate.
dwWaitResult = WaitForSingleObject(
sem, // handle to semaphore
INFINITE); // zero-second time-out interval
int rightIndex = 0;
int left = 0;
int difference = g_targetNumber;
switch (dwWaitResult)
{
// The semaphore object was signaled.
case WAIT_OBJECT_0:
//// TODO: Perform task
bContinue = FALSE;
rightIndex = /*firstRun ?*/ pLH->sourceList.size() - 1 /*: iterator - 1*/;
left = (rightIndex - 1);
//TODO: test Added 9/24/2019
if (rightIndex < 0)
return FALSE;
while ((difference = NewSolution::Difference(pLH->sourceList)) > 0) {
pLH->sourceList[rightIndex]++;
}
pLH->NewDescendantFound(&pLH->sourceList);
ShowCombination(pLH->sourceList);
while (
pLH->RebuildCombination(pLH->sourceList, rightIndex)
)
{
--rightIndex;
}
pLH->combinationStorage.DeleteDescendants();
// Release the semaphore when task is finished
if (!ReleaseSemaphore(
sem, // handle to semaphore
1, // increase count by one
NULL)) // not interested in previous count
{
//printf("ReleaseSemaphore error: %d\n", GetLastError());
}
break;
// The semaphore was nonsignaled, so a time-out occurred.
case WAIT_TIMEOUT:
//printf("Thread %d: wait timed out\n", GetCurrentThreadId());
break;
}
delete pLH;
return TRUE;
}
}; // CombinationListHandler
} // New Solution //
Set::ListOfSets NewSolution::ListHandler::startingCombinations;
bool InitializeStreams()
{
try {
g_inputStream = std::ifstream();
g_inputStream.open("input.txt");
g_outputStream = std::ofstream();
g_outputStream.open("output.txt", std::ios::trunc);
return true;
} catch (...) {
return false;
}
}
void Output()
{
g_outputStream << g_threadCount;
g_outputStream << std::endl;
g_outputStream << g_targetNumber;
g_outputStream << std::endl;
g_outputStream << g_millisecondsSpentOutputStr;
g_outputStream << std::endl;
}
void CloseStreams()
{
g_inputStream.close();
g_outputStream.close();
}
bool InitializeInputData() {
try {
g_threadCount = -1;
g_targetNumber = -1;
// Read count of threads from the file
std::string tempLine;
std::getline(g_inputStream, tempLine);
g_threadCount = std::stoi(tempLine);
// Read the target number from the file
std::getline(g_inputStream, tempLine);
g_targetNumber = std::stoi(tempLine);;
if (g_threadCount == -1 || g_targetNumber == -1) {
return false;
}
} catch (...) {
return false;
}
return true;
}
void RunNewSolutionMultiThreaded() {
SimpleTimer::SimpleTimer simpleTimer = SimpleTimer::SimpleTimer();
g_countOfCombinations = 0;
NewSolution::ListHandler::InitializeCombinations(g_targetNumber);
for (int i = 0
; i < NewSolution::ListHandler::startingCombinations.size();
i++)
{
NewSolution::ListHandler::ShowList(*NewSolution::ListHandler::startingCombinations[i]);
}
sem = CreateSemaphore(
NULL, // default security attributes
1, // initial count
g_threadCount, // maximum count
NULL); // unnamed semaphore
if (sem == NULL)
{
printf("CreateSemaphore error: %d\n", GetLastError());
}
// Initialize the critical section one time only.
if (!InitializeCriticalSectionAndSpinCount(&cs,
0x00000400))
return;
// Create worker threads
DWORD ThreadID;
threads = new HANDLE[NewSolution::ListHandler::startingCombinations.size()];
for (int i = 0; i < NewSolution::ListHandler::startingCombinations.size(); i++)
{
threads[i] = 0;
}
int lastThreadID = -1; int i = 0;
for (int i = 0;
i < NewSolution::ListHandler::startingCombinations.size();
i++
)
{
auto it = NewSolution::ListHandler::startingCombinations._collection[i];
if (NewSolution::Difference(*it) == 0) {
g_countOfCombinations++;
//NewSolution::ListHandler::ShowCombination(*it);
continue;
}
++lastThreadID;
NewSolution::ListHandler* listHandler = new NewSolution::ListHandler(it, it->size());
listHandler->DeleteInnerDescendants();
//listHandler->FindAllSumsFixedLength();
threads[lastThreadID] = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE)NewSolution::ListHandler::FindAllSumsFixedLengthMT,
(LPVOID)listHandler, // thread function argument
0, // default creation flags
&ThreadID); // receive thread identifier
if (threads[lastThreadID] == NULL)
{
printf("CreateThread error: %d\n", GetLastError());
return;
}
}
// Wait for all threads to terminate
WaitForMultipleObjects(lastThreadID + 1, threads, TRUE, INFINITE);
// Close thread and semaphore handles
for (int i = 0; i <= lastThreadID; i++)
CloseHandle(threads[i]);
delete[] threads;
CloseHandle(sem);
// Release resources used by the critical section object.
DeleteCriticalSection(&cs);
//NewSolution::ListHandler::startingCombinations.~ListOfSets();
std::cout << "Count of combinations " << g_countOfCombinations /*+ g_targetNumber-1*/ << std::endl;
std::cout << "*** New Solution Execution Completed ***" << std::endl;
// Counting time spent
g_millisecondsSpentOutputStr = simpleTimer.StopMilliseconds();
std::cout << "Time spent: " << g_millisecondsSpentOutputStr << std::endl;
}
int main()
{
g_countOfCombinations = 0;
if (
!InitializeStreams()
) {
std::cout << "File \"input.txt\" doesn't exist. Quiting..." << std::endl;
system("pause");
return 1;
}
if ( !InitializeInputData() ) {
std::cout << "Input file is currupted... Quiting..." << std::endl;
system("pause");
return 1;
}
RunNewSolutionMultiThreaded();
Output();
CloseStreams();
system("pause");
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.