C ++多线程性能比单线程代码慢

Use*_*222 2 c++ multithreading

我正在学习在c ++中使用线程,
我用整数创建了一个很长的向量,并设置了另一个整数x。我想计算该整数与向量中整数之间的差。

但是,在我的实现中,使用两个线程的函数比使用单个线程的函数要慢。我想知道为什么是原因,以及如何正确实现线程以使其运行得更快。

这是代码:

#include <iostream>
#include <vector>
#include <thread>
#include <future>
#include <math.h>

using namespace std;


vector<int> vector_generator(int size) {
    vector<int> temp;
    for (int i = 0; i < size; i++) {
        temp.push_back(i);
    }
    return temp;
}

vector<int> dist_calculation(int center, vector<int> &input, int start, int end) {
    vector<int> temp;
    for (int i = start; i < end; i++) {
        temp.push_back(abs(center - input[i]));
    }
    return temp;
}


void multi_dist_calculation(int center, vector<int> &input) {
    int mid = input.size() / 2;

    vector<int> temp1(input.begin(), input.begin() + mid);
    vector<int> temp2(input.begin()+mid, input.end());

    auto future1 = async(dist_calculation, center, temp1, 0, mid);
    auto future2 = async(dist_calculation, center, temp2, 0, mid);

    vector<int> result1 = future1.get();
    vector<int> result2 = future2.get();

    return;
}


int main() {

    vector<int> v1 = vector_generator(1000000000);
    vector<int> result;
    multi_dist_calculation(0, v1);
    //dist_calculation(50, v1, 0, v1.size());

    return 0;
}
Run Code Online (Sandbox Code Playgroud)



更新#1

添加了std :: launch :: async&reserve()的建议,它确实使代码更快。但是2线程函数仍然比单线程函数慢。我可以说在这种计算中,单线程更快吗?

#include <iostream>
#include <vector>
#include <thread>
#include <future>
#include <math.h>

using namespace std;


vector<int> vector_generator(int size) {
    vector<int> temp;
    temp.reserve(size);
    for (int i = 0; i < size; i++) {
        temp.push_back(i);
    }
    return temp;
}

vector<int> dist_calculation(int center, vector<int> &input, int start, int end) {
    vector<int> temp;
    temp.reserve(end - start);
    for (int i = start; i < end; i++) {
        temp.push_back(abs(center - input[i]));
    }
    return temp;
}


void multi_dist_calculation(int center, vector<int> &input) {
    int mid = input.size() / 2;

    auto future1 = async(std::launch::async, dist_calculation, center, input,   0, mid);
    auto future2 = async(std::launch::async, dist_calculation, center, input, mid, input.size());

    vector<int> result1 = future1.get();
    vector<int> result2 = future2.get();

    return;
}


int main() {

    vector<int> v1 = vector_generator(1000000000);
    vector<int> result;
    int center = 0;
    multi_dist_calculation(center, v1);
    //dist_calculation(center, v1, 0, v1.size());

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Fir*_*cer 6

您没有将任何东西传递std::launch policy给std::async,因此它给实现留下了很多自由。

行为就好像(2)在策略为std :: launch :: async |的情况下被调用| std :: launch ::递延。换句话说,当查询结果std :: future以获取值时,f可以在另一个线程中执行,也可以同步运行。

但也请注意,更普遍地,使用更多线程,尤其是在执行小型任务时,可能不会更快。

  • dist_calculation您想穿线的地方或任何任务都是少量的工作,请注意开销。创建新线程的成本相对较高,并且任何内部池std::async使用,承诺和未来都会产生开销。
  • 此外,按照编写方式,可能会创建更多的向量,具有更多的动态内存,并且需要合并结果,这也会带来一些成本。
  • 在更复杂的情况下,如果std::mutex涉及同步(例如与同步),则可能会比其他线程获得更多的性能。
  • 在某些情况下,瓶颈将不是CPU。例如,可能是磁盘/存储速度(包括页面/交换文件的速度),网络速度(包括远程服务器),甚至是内存带宽(除了NUMA感知的优化之外,它们都比仅使用复杂得多std::async)。这些中的多线程只会增加开销,但没有好处。

您应该首先尽可能利用其他基本优化方法,例如reserve向量的大小,以避免不必要的分配和复制,resize并且可以使用vector[index] = a代替push_back,等等。

对于简单的事情,abs(centre - input[i])您可以从SIMD(单指令多数据)优化中获得更多改进。例如,确保您正在使用诸如SSE2启用之类的任何优化进行编译,并且如果编译器没有适当地优化循环(我认为push_back可能会干扰,测试!),则对其进行稍作更改,甚至可以显式地使用矢量指令(用于x86检出_mm_add_epi32等)。