当前位置: 首页 > 知识库问答 >
问题:

C并发队列:>1个线程时速度较慢

颜畅
2023-03-14

队列并发两个不同的锁:一个用于 enqueue() 以保护同时排队的多个线程

如果队列已满,Add(enqueue)将跳过(返回)插入。如果队列为空,则删除(出列)将跳过删除。

我使用doRandon()生成了一堆0到1之间的随机数。我使用这些数字来决定是否添加/删除。

性能:我已尝试使用静态/动态线程分配测试队列。的执行时间

   //g++ -std=c++0x -pthread -o block blocking.cpp;./block

    #include <iostream>
    #include <thread>
    #include <mutex>
    #include <atomic>
    #include <random>
    #include <stdio.h>  
    #include <time.h>
    #include <stdlib.h>
    #include <ctime>
    #include <condition_variable>
    using namespace std;

    #define NUMBER_OF_THREADS 1
    #define NUMBER_OF_OPERATIONS 10000000
    #define QUEUE_CAPACITY 1000000

    std::vector<double> getRandom();


    template <class T> class BoundedQueue {

        private:
            T * array;  
            int head, tail, capacity;
            std::mutex enqLock, deqLock;
            std::atomic<long> sharedCounter;
            std::condition_variable notEmptyCondition, notFullCondition;    

        public:
            void staticAllocation(double randomNumbers[], int threadID);
            void dynamicAllocation(double randomNumbers[]);
            void add (T x);
            BoundedQueue ();
            void remove ();
    };

    template <class T> BoundedQueue<T>::BoundedQueue () {
        capacity = QUEUE_CAPACITY;
        array = new T[capacity];
        head = 0;
        tail = 0;
        sharedCounter = 0;
    }

    template <class T> void BoundedQueue<T>::add (T x) {

            enqLock.lock();

            if (tail - head == capacity) {
                enqLock.unlock();
                return;
            }
            array[tail % capacity] = x;
            tail++;

            enqLock.unlock();
    }   

    template <class T> void BoundedQueue<T>::remove() {

            deqLock.lock();
            if (tail - head == 0) {
                deqLock.unlock();
                return;
            }
            T result = array [head % capacity];
            head++;

            deqLock.unlock();
    }   

    template <class T> void BoundedQueue<T>::dynamicAllocation(double randomNumbers[]) {

        long i = 0;
        while (i < QUEUE_CAPACITY) {
            i = sharedCounter.fetch_add(1, std::memory_order_relaxed);
            if(randomNumbers[i] <= 0.5) add(0);
            else remove();
        }   
    }

    template <class T> void BoundedQueue<T>::staticAllocation (double randomNumbers[], int threadID) {

        int split = NUMBER_OF_OPERATIONS / NUMBER_OF_THREADS;   
        for (int i = threadID * split; i < (threadID * split) + split; i++) {
            if(randomNumbers[i] <= 0.5) add(0);
            else remove();
        }
    }

    std::vector<double> getRandom() {

        std::vector<double> numbers;
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_real_distribution<> dis(0,1);

        for(int i = 0; i < NUMBER_OF_OPERATIONS; i++) numbers.push_back(dis(gen));

        return numbers;
    }   

    int main () {

        BoundedQueue<int> bQ;
        std::vector<double> temp = getRandom();
        double* randomNumbers = &temp[0];

        std::thread myThreads[NUMBER_OF_THREADS];

        clock_t begin = clock();

        for(int i = 0; i < NUMBER_OF_THREADS; i++) {
                    myThreads[i] = std::thread ( [&] {bQ.dynamicAllocation(randomNumbers); });
        }

        for(int i = 0; i < NUMBER_OF_THREADS; i++) {
            if(myThreads[i].joinable()) myThreads[i].join();
        }   

        clock_t end = clock();

        cout << double(end-begin) * 1000 / CLOCKS_PER_SEC;
        return 0;
    }

共有1个答案

薛烨
2023-03-14

这里没有相似之处。请注意,所有的线程几乎都被序列化了,因为您在函数开始时获取了一个锁,并在函数结束时释放了它。

尽管由于缺乏并行性,工作在线程之间进行分配,但锁定/解锁开销占主导地位,总体而言,与单线程相比,执行时间较长。

因此,存在并发性,但没有并行性,我们只是付出了同步的代价,而没有性能优势。

 类似资料:
  • 我编写了一个简单的类,我计划将其扩展为客户端套接字编程应用程序的一部分。类涉及一个BlockingQueue(我从这里复制了代码:相当于Java的BlockingQueue的C++)。当我创建了下面的包装类的一个实例后,我打算让它生成一个单独的线程,该线程只需执行BlockingQueue上阻塞的printer()函数,直到有一个或多个字符串可用,然后它只需将字符串打印到控制台窗口。在我的预期应用

  • 我需要一个库或我们的软件工具,可以: 1)将线程/作业/任务(任何东西--如果需要,我们可以重写代码,我们在mintue有线程对象)放入像system这样的队列中2)我们可以定义同时最多运行多少线程3)线程完成后,线程从队列中移除,这样GC就可以移除所有涉及的实体。 我正在进行大量阅读,发现ExecutorService(Executors.newFixedThreadPool(5);)但问题可能

  • 在使用TensorFlow进行异步计算时,队列是一种强大的机制。 正如TensorFlow中的其他组件一样,队列就是TensorFlow图中的节点。这是一种有状态的节点,就像变量一样:其他节点可以修改它的内容。具体来说,其他节点可以把新元素插入到队列后端(rear),也可以把队列前端(front)的元素删除。 为了感受一下队列,让我们来看一个简单的例子。我们先创建一个“先入先出”的队列(FIFOQ

  • 问题 你有一个线程队列集合,想为到来的元素轮询它们, 就跟你为一个客户端请求去轮询一个网络连接集合的方式一样。 解决方案 对于轮询问题的一个常见解决方案中有个很少有人知道的技巧,包含了一个隐藏的回路网络连接。 本质上讲其思想就是:对于每个你想要轮询的队列,你创建一对连接的套接字。 然后你在其中一个套接字上面编写代码来标识存在的数据, 另外一个套接字被传给 select() 或类似的一个轮询数据到达

  • 问题内容: 也许这是一个愚蠢的问题,但我似乎找不到一个明显的答案。 我需要一个仅包含唯一值的并发FIFO队列。尝试添加队列中已经存在的值只会忽略该值。如果不是为了线程安全,那将是微不足道的。在Java中是否存在数据结构,或者在Interweb上是否存在代码snipit表现出这种行为? 问题答案: 如果您想要比完全同步更好的并发性,那么我知道有一种方法可以使用ConcurrentHashMap作为支

  • 本文向大家介绍C#线程队列用法实例分析,包括了C#线程队列用法实例分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#线程队列用法。分享给大家供大家参考。具体如下: 希望本文所述对大家的C#程序设计有所帮助。