简体   繁体   English

使用并行线程查找加起来为给定数字的所有组合

[英]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.

相关问题 如何找到添加两个变量的所有可能组合,每个变量都附加到一个乘数,总和为给定的数字(cin)? - How to find all possible combinations of adding two variables, each attached to a multiplier, summing up to a given number (cin)? 使用提供的线程数进行并行基数排序 - Parallel radix sort using a provided number of threads 查找x ^ n的所有组合,并检查它们加起来是否等于一个数字,但不包括相同的数字 - Find all combinations for x^n and check if they add up to a number excluding same numbers 生成直至给定数字N的步进数 - Generate stepping numbers upto a given number N 对于给定的整数a,找到总和为a的所有唯一正整数组合 - For a given integer a, find all unique combinations of positive integers that sum up to a 从给定字符串中查找长度为k的所有排列/组合 - Find all permutations/combinations of length k from given string 使用给定数量的线程查找两个数字之间范围内的所有素数 - Find all primes in a range between two numbers using a given amount of threads 查找组合数量的算法 - Algorithm to find number of combinations 生成添加到特定数字的所有唯一数字组合 - Generate all of the unique combinations of numbers that add up to a certain number 使用多个求和找到有序集合的组合数 - Find number of combinations of ordered set using multiple summations
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM