【问题标题】:Simple Time Comparison Multithreading Program in C++ (and 4 questions)C++ 中的简单时间比较多线程程序(和 4 个问题)
【发布时间】:2021-09-18 08:55:27
【问题描述】:

我有 C++ 方面的经验,我正在尝试使用该语言学习多线程。 我刚刚编写了以下程序(代码下方的问题)来比较一个一个运行十个函数调用与并行运行的时间效率。

我的四个问题是:

  1. 这是线程库的正确用法吗?时间似乎是合理的,因为线程应该快得多,但我是这个功能的新手,想确定我做得对。如果该程序有任何改进,请告诉我。

  2. 输出(在代码下方)是预期的吗?线程试图同时打印到控制台,因此在换行之前写入了一些字符或打印了其他值的字符,例如:3 + 5 = 84 + 5 = (new line) 9,而不是3 + 5 = 8(新行)4 + 5 = 9。这种行为是预期的吗?

  3. 也将不胜感激有关此主题的任何类型的阅读材料或建议!我一直在阅读文章,并计划很快观看一些有关多线程的视频。

  4. 每次运行的输出时间都不一样。当然这是意料之中的,但有时,多线程运行比逐个函数调用运行慢。这应该发生吗?


#include <iostream>
#include <thread>
#include <time.h>
#include <chrono>
#include <ctime>

using namespace std;

void add(int num) {
    cout << num << " + 5 = " << num + 5 << endl;
}

int main()
{
    int a, b, c, d, e, f, g, h, i, j;
    a = 0;
    b = 1;
    c = 2;
    d = 3;
    e = 4;
    f = 5;
    g = 6;
    h = 7;
    i = 8;
    j = 9;
    
    cout << "Starting timer for no multithreading" << endl;

    std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();
    add(a);
    add(b);
    add(c);
    add(d);
    add(e);
    add(f);
    add(g);
    add(h);
    add(i);
    add(j);
    std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();

    cout << "Stopped timer for no multithreading" << endl;

    std::chrono::duration<double> total1 = std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1);

    cout << "Without multithreading, the ten function calls took: " << total1.count() << " seconds to complete." << endl;
    

    cout << endl << endl;

    thread A(add, a);
    thread B(add, b);
    thread C(add, c);
    thread D(add, d);
    thread E(add, e);
    thread F(add, f);
    thread G(add, g);
    thread H(add, h);
    thread I(add, i);
    thread J(add, j);

    cout << "Starting timer for multithreading" << endl;

    std::chrono::high_resolution_clock::time_point t3 = std::chrono::high_resolution_clock::now();
    A.join();
    B.join();
    C.join();
    D.join();
    E.join();
    F.join();
    G.join();
    H.join();
    I.join();
    J.join();
    std::chrono::high_resolution_clock::time_point t4 = std::chrono::high_resolution_clock::now();

    cout << "Stopped timer for multithreading" << endl;

    std::chrono::duration<double> total2 = std::chrono::duration_cast<std::chrono::duration<double>>(t4 - t3);

    cout << "With multithreading, the ten function calls took: " << total2.count() << " seconds to complete." << endl;
    //cout << total2 << "seconds" << endl;
    

    return 0;
}

输出是:

Starting timer for no multithreading
0 + 5 = 5
1 + 5 = 6
2 + 5 = 7
3 + 5 = 8
4 + 5 = 9
5 + 5 = 10
6 + 5 = 11
7 + 5 = 12
8 + 5 = 13
9 + 5 = 14
Stopped timer for no multithreading
Without multithreading, the ten function calls took: 0.0016732 seconds to complete.


0 + 5 = 5
1 + 5 = 6
2 + 5 = 7
3 + 5 = 84 + 5 =
9
5 + 5 = 106 + 5 = 11
7 + 5 =
12
8 + 5 = 13
Starting timer for multithreading9 + 5 = 14

Stopped timer for multithreading
With multithreading, the ten function calls took: 5.07e-05 seconds to complete.

提前谢谢你:D

【问题讨论】:

  • 更多线程不会自动更快。您只有一个可以显示输出的控制台
  • “输出是预期的吗?”。是的。 std::cout 不是隐式线程安全的。
  • @DrewDormann 它在单个字符级别上是线程安全的,但这并不能防止输出被打乱
  • 请专注于一个问题。 3. 离题
  • 我建议您阅读有关 Amdahl'sGustafson's 的法律。它们对于理解为什么更多线程并不总是更快以及如何充分利用多线程至关重要

标签: c++ multithreading visual-c++ thread-safety


【解决方案1】:

这不是测量时间的正确方法。

thread A(add, a);

在这里,将创建一个线程对象,它可能会立即执行该函数(取决于操作系统调度程序)。

A.join();

在这里,您正在等待线程完成。

你的基本流程是

thread A(add, a);
start timer
A.join()
end timer.

因此,您的计时器测量等待线程完成 + 执行一些倒霉线程所花费的时间。

另外,std::cout 不是线程安全的。

【讨论】:

  • std::cout 是线程安全的。当多个线程同时写入std::cout 时,不存在数据竞争。虽然同步是在单个字符级别上。不确定什么是正确的词,但“非线程安全”表明您在从多个线程写入时由于数据竞争而存在未定义的行为,但事实并非如此,只是输出可以交错,但这与安全无关
  • 我明白了,我更改了计时器以在“thread A(add, a)”之前的行开始,并在“thread J(add, j)”之后的行结束。这是正确的方法吗?另外,是否有线程安全的打印功能可供选择?此外,我发现每次运行的两个总时间都不同,有时多线程的速度比一对一的部分更快,而其他时间则慢。这是可以预料的吗?谢谢
  • @463035818_is_not_a_number 你是对的,它是线程安全的,但输出可能交错。
  • @HusamChekfa 如果你在线程 A(add, a) 之前添加它,它将测量线程创建时间 + 执行时间 + 完成等待时间。线程创建很昂贵(内存分配+系统调用)。线程连接也很昂贵(系统调用)。由于您正在测量一些随机时间(在测量开始时,一些线程已经完成执行),因此您的输出不可靠。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多