【问题标题】:C++: divide a loop into several threadsC++:将一个循环分成几个线程
【发布时间】:2023-02-17 04:09:08
【问题描述】:

首先,我完全是 C++ 的初学者,这就是为什么如果这个问题可能很愚蠢(或者可能没有任何意义),我深表歉意,但我完全不知道在我的情况下我能做什么。

所以,我最近一直在尝试学习多线程,因为我认为使用线程而不是在整个大内容(即文件的内容)上运行的简单循环来获得更好的方法实际上速度更快。

这是我实际拥有的代码(不完整,但在这种情况下并不重要):


int end = 40000;
std::string content; // this variable is filled before calling the function "another_function", don't mind it

// this function is completely useless, this is just for testing purposes
void dummy_function(int *idx, int value_to_divide) {
    std::list<int> test;

    for (; *idx <= ending / div; *idx++) {
        int count = 100 + *i;
        test.insert(test.end(), { 1, 2, 3, count });
        std::cout << content.c_str() + *i << endl;
        test.clear();
    }
}

void another_function() {
    int idx = 0;

    std::vector<std::thread> th;

    for (int j = 4; j != 0; j--) {
        th.push_back(std::thread(&dummy_function, &idx + ((j != 4) ? (end / (j + 1)) : 0), j));
    }

    for (auto& thread:th)
        thread.join();
}

我如何看待我所做的是我将内容变量的读取分成 4 个线程(使它们同时停止,因为它们应该具有相同的长度),第一个从 0(开始)开始,第二个一个开始于 (i + (end / 3)), 等等...

但是,当第一个线程停止时它会发生段错误,实际上其他线程甚至没有从我认为它们会开始的地方开始,所以也许我一开始甚至不理解线程的概念(正如我所说的我是一个这个大声笑的初学者)。

我听说过一种叫做“安全队列”或“安全线程”的东西(使用互斥锁和相关的东西),但我似乎不明白如何在我的案例中使用它。

有人能够解释我如何让这些线程并行运行并且“安全地”运行吗?

谢谢 :)

【问题讨论】:

  • 有一本书《C++ 并发实战》
  • 如果你是 C++ 的初学者,那么在深入线程之前先了解更多 C++,至少了解:std::thread、std::async、std::mutex、std::scoped_lock、std::condition_variable、lambda 函数和他们的俘虏。并且知道线程也是有代价的,仅仅在一个问题上投入 n 个线程不会让它运行得快 n 倍,并且代码的复杂性也会增加。有关我提到的类的更多信息,请查看 cppreference。 (最后你也只需要积累经验)
  • 如果您真的是一个完全的初学者,您可能不应该使用多线程编写代码;他们可能很棘手。先把基础打好,再做更复杂的事情。
  • 好吧,我相信实践总比什么都不做要好,因为我必须从某个地方开始,但是是的,你们都是对的(即使我会学习 Pepijin 所说的一切,我至少想知道为什么会出现段错误哈哈)
  • 由于丑陋的行&amp;idx + ((j != 4) ? (end / (j + 1)) : 0),它肯定会导致段错误。我不知道你想用它做什么,但这会导致一个错误的指针,因此稍后取消引用它会导致未定义的行为,这在实践中可能是一个段错误。首先尝试编写没有线程的代码,因为这个问题不是由于线程引起的。此外,请注意链表通常很慢,因此尝试使用多线程来加速此类代码当然不是最佳选择:首先考虑优化顺序代码(尤其是对于基于 IO 的代码)。

标签: c++ multithreading thread-safety


【解决方案1】:

这不是线程问题。它远比这更基本。

这是你的代码:

void another_function() {
    int idx = 0;

    std::vector<std::thread> th;

    for (int j = 4; j != 0; j--) {
        th.push_back(std::thread(&dummy_function, &idx + ((j != 4) ? (end / (j + 1)) : 0), j));
    }

    for (auto& thread:th)
        thread.join();
}

idx 是堆栈上的单个整数。您正在传递 idx 的地址加上您正在计算的一些偏移量。然后您的函数假定这是一个很好的地址。

但这不是一个好的地址。它指出谁知道什么。您没有在任何地方分配 40000 个整数。你正好有 1。

现在,我不确定你还想做什么,但你可以稍微改变 idx :

     int idx[40000];

然后我不会完全相同地执行 for 循环。反而:

    for (int j = 4; j != 0; j--) {
        int offset = j != 4 ? end / (j + 1) : 0;
        th.push_back(std::thread(&dummy_function, &idx[offset], j));
    }

或类似的东西。不过,我认为您调用的方法不会令人满意,您最好传入整个数组,然后传入开始 + 长度或开始 + 停止值。

但是您的主要问题是因为您在随机内存上猖獗。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-28
    • 1970-01-01
    相关资源
    最近更新 更多