简体   繁体   中英

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

#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()

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/

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

Parallelizing recursive function using OpenMP in C++

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. 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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM