多线程嵌套 for 循环 std::thread

Multithreading nested foor loop with std::thread

我是 c++ 的新手,我真的需要一些关于使用 std::thread 的多线程的建议。 我有以下代码,它基本上使用 thread:

分隔 N = 8^L 迭代(最多 8^14)的 for 循环
void Lanczos::Hamil_vector_multiply(vec& initial_vec, vec& result_vec) {
result_vec.zeros();
        std::vector<arma::vec> result_threaded(num_of_threads);
        std::vector<std::thread> threads;
        threads.reserve(num_of_threads);
        for (int t = 0; t < num_of_threads; t++) {
            u64 start = t * N / num_of_threads;
            u64 stop = ((t + 1) == num_of_threads ? N : N * (t + 1) / num_of_threads);
            result_threaded[t] = arma::vec(stop - start, fill::zeros);
            threads.emplace_back(&Lanczos::Hamil_vector_multiply_kernel, this, start, stop, ref(initial_vec), ref(result_vec));
        }for (auto& t : threads) t.join();
}

其中Lanczos是我的一般class(其实不需要知道它包含什么),而成员函数Hamil_vector_multiply_kernel的形式是:

void Lanczos::Hamil_vector_multiply_kernel(u64 start, u64 stop, vec& initial_vec, vec& result_vec_threaded){
       // some declarations
    for (u64 k = start; k < stop; k++) {
        // some prealiminary work
        for (int j = 0; j <= L - 1; j++) {
             // a bunch of if-else statements, where result_vec_threaded(k) += something
        }
    }
}

(代码很长,所以我没有把整个whing贴在这里)。我的问题是我在另一个函数中调用函数 Hamil_vector_multiply 100-150 次,所以我每次都创建一个新的线程向量,然后破坏 itself.My 问题:

  1. 是否最好在调用 Hamil_vector_multiply 的函数中创建线程,然后将线程向量传递给 Hamil_vector_multiply 以避免每次都创建新线程?

  2. 异步攻击循环会更好吗(例如,第一个完成迭代的线程开始下一个可用的线程?如果是的话,你能指出任何描述异步线程的文献吗?

3)是否有更好的多线程方式来处理这样的循环? (没有多线程我有一个从k=0到k=N=8^14的循环,这会占用很多时间)

  1. 我发现了几次创建线程池和作业队列的尝试,例如使用这样的一些工作池是否有用:https://codereview.stackexchange.com/questions/221617/thread-pool-c-implementation

我的代码按预期工作(给出了正确的结果),它提高了程序的速度,大约是 16 核的 10 倍。但是,如果您有其他与多线程无关的有用评论,我将不胜感激每一条建议

非常感谢您!

PS:调用Hamil_vector_multiply 100-150次的函数形式为:

void Lanczos::Build_Lanczos_Hamil(vec& initial_vec) {
   vec tmp(N);
   Hamil_vector_multiply(initial_vec, tmp);
   // some calculations
   for(int j=0; j<100; j++{
      // somtheing
      vec tmp2 = ...
      Hamil_vector_multiply(tmp2, tmp);
     // do somthing else  -- not related 
   }
}

Is it better to create threads in the function which calls Hamil_vector_multiply and then pass a vector of threads to Hamil_vector_multiply in order to avoid creating each time new threads?

如果您担心性能,是的,这会有所帮助。您现在所做的实际上是在每个函数调用中分配一个新的堆块(我说的是向量)。如果你能事先做到这一点,它会给你一些性能。这样做没有问题,但您可以获得一些性能。

Would it be better to asynchronously attack the loop (for instance the first thread to finish an iterations starts the next available? If yes can you point to any literature describing threads asynchronously?

这可能不是个好主意。在多个线程之间共享相同数据时,您将不得不使用互斥体锁定资源。这意味着您将获得与使用一个线程进行处理相同的性能,因为其他线程必须等待资源解锁并准备好使用。

Are there maybe better ways of multithreading such a loop? (without multithreading i have a loop from k=0 to k=N=8^14, which takes up a lot of time)

如果您的目标是提高性能,如果您可以将其放入多个线程中,最重要的是如果多线程会有所帮助,那么没有理由不这样做。据我所知,您的实现看起来非常简洁。但请记住,启动线程本身的成本有点高(与您的性能提升相比可以忽略不计),负载平衡肯定会进一步提高性能。

But if you have other helpful comments not regarding multithreading I woul be grateful for every piece of advice

如果每个线程的负载可能不同,那么考虑负载平衡将是一项很好的投资。除此之外,我没有发现问题。需要改进的主要地方是您的逻辑本身。如果您的逻辑需要大量时间,线程可以做很多事情..

可选:
您可以使用 std::future 来实现它的额外好处是它在销毁时异步启动线程,这意味着当您的线程池销毁时(当向量超出范围时),它将启动线程。但它 可能 会干扰你的第一个问题。