gpt4 book ai didi

c++ - 线程彼此减慢

转载 作者:行者123 更新时间:2023-12-01 14:52:30 25 4
gpt4 key购买 nike

我有一些昂贵的计算,我想在一组线程上进行划分和分配。
我将我的代码简化为一个仍在发生的最小示例。

简而言之:

我有 N 个要划分为“线程”线程的任务。

每个任务都是运行一堆简单数学运算的以下简单函数。
(实际上,我在这里验证不对称签名,但为了简化起见,我排除了它)

while (i++ < 100000)
{
for (int y = 0; y < 1000; y++)
{
sqrt(y);
}
}

使用 1 个线程运行上述代码会导致每次操作 0.36 秒(最外层的 for 循环),因此总执行时间约为 36 秒。

因此,并行化似乎是一种明显的加速方法。但是,使用两个线程时,操作时间上升到 0.72 秒,完全破坏了任何加速。

添加更多线程通常会导致性能越来越差。

我有一个 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz,有 6 个物理内核。
所以我希望至少在从 1 到 2 个线程时使用性能提升。但事实上,当增加线程数时,每个操作都会变慢。

难道我做错了什么?

完整代码:
using namespace std;

const size_t N = 100;
const size_t Threads = 1;

atomic_int counter(0);

struct ThreadData
{
int index;
int count;

ThreadData(const int index, const int count): index(index), count(count){};
};

void *executeSlave(void *threadarg)
{
struct ThreadData *my_data;
my_data = static_cast<ThreadData *>(threadarg);
for( int x = my_data->index; x < my_data->index + my_data->count; x++ )
{
cout << "Thread: " << my_data->index << ": " << x << endl;

clock_t start, end;
start = clock();
int i = 0;

while (i++ < 100000)
{
for (int y = 0; y < 1000; y++)
{
sqrt(y);
}
}
counter.fetch_add(1);

end = clock();
cout << end - start << ':' << CLOCKS_PER_SEC << ':' << (((float) end - start) / CLOCKS_PER_SEC)<< endl;
}

pthread_exit(NULL);
}

int main()
{
clock_t start, end;
start = clock();

pthread_t threads[Threads];
vector<ThreadData> td;
td.reserve(Threads);
int each = N / Threads;
cout << each << endl;
for (int x = 0; x < Threads; x++) {
cout << "main() : creating thread, " << x << endl;
td[x] = ThreadData(x * each, each);

int rc = pthread_create(&threads[x], NULL, executeSlave, (void *) &td[x]);

if (rc) {
cout << "Error:unable to create thread," << rc << endl;
exit(-1);
}
}

while (counter < N) {
std::this_thread::sleep_for(10ms);
}

end = clock();

cout << "Final:" << endl;
cout << end - start << ':' << CLOCKS_PER_SEC << ':' << (((float) end - start) / CLOCKS_PER_SEC)
<< endl;

}

最佳答案

clock() 返回整个进程的近似 CPU 时间。

最外层循环每次迭代执行固定数量的工作

    int i = 0;
while (i++ < 100000)
{
for (int y = 0; y < 1000; y++)
{
sqrt(y);
}
}

因此,围绕此循环报告的进程 CPU 时间将与正在运行的线程数成正比(每个线程仍需要相同的时间,乘以 N 个线程)。

使用 std::chrono::steady_clock 改为测量挂钟时间。还要注意 I/O 例如 std::cout需要很多挂钟时间并且不稳定。因此,由于内部的 I/O,测得的总耗时会出现偏差。

一些补充说明:
  • sqrt()的返回值从未使用过;编译器可能会完全消除调用。以某种方式使用该值是谨慎的做法。
  • void* executeSlave()没有返回 void*指针值 (UB)。它可能应该简单地声明void如果它什么都不返回。
  • td.reserve(Threads)保留内存但不分配对象。 td[x]然后访问不存在的对象(UB)。使用td.emplace_back(x * each, each)而不是 td[x] = ... .
  • 技术上不是问题,但建议使用标准 C++ std::thread而不是 pthread ,以获得更好的便携性。

  • 通过以下内容,我看到与线程数成正比的正确加速:
    #include <string>
    #include <iostream>
    #include <vector>
    #include <atomic>
    #include <cmath>
    #include <thread>

    using namespace std;
    using namespace std::chrono_literals;

    const size_t N = 12;
    const size_t Threads = 2;

    std::atomic<int> counter(0);
    std::atomic<int> xx{ 0 };

    void executeSlave(int index, int count, int n)
    {
    double sum = 0;
    for (int x = index; x < index + count; x++)
    {
    cout << "Thread: " << index << ": " << x << endl;
    auto start = std::chrono::steady_clock::now();
    for (int i=0; i < 100000; i++)
    {
    for (int y = 0; y < n; y++)
    {
    sum += sqrt(y);
    }
    }
    counter++;

    auto end = std::chrono::steady_clock::now();
    cout << 1e-6 * (end - start) / 1us << " s" << endl;
    }
    xx += (int)sum; // prevent optimization

    }

    int main()
    {
    std::thread threads[Threads];
    int each = N / Threads;
    cout << each << endl;
    auto start = std::chrono::steady_clock::now();
    for (int x = 0; x < Threads; x++) {
    cout << "main() : creating thread, " << x << endl;
    threads[x] = std::thread(executeSlave, x * each, each, 100);
    }

    for (auto& t : threads) {
    t.join();
    }

    auto end = std::chrono::steady_clock::now();

    cout << "Final:" << endl;
    cout << 1e-6 * (end - start) / 1us << " s" << endl;

    }

    关于c++ - 线程彼此减慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62215840/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com