C++STL多线程,并行运行计算

C++ STL Multithreading, running computation in parallel

本文关键字:运行 计算 并行 多线程 C++STL      更新时间:2023-10-16
#include <iostream>
#include <cmath>
#include <numeric>
#include <vector>
#include <algorithm>
#include <thread>
#include <stdio.h>

// Determines if a point of dimension point.size() is within the sphere
bool isPointWithinSphere(std::vector<int> point, const double &radius) {
// Since we know that the sphere is centered at the origin, we can     simply
// find the euclidean distance (square root of the sum of squares) and check to
// see if it is less than or equal to the length of the radius 
//square each element inside the point vector
std::transform(point.begin(), point.end(), point.begin(), [](auto &x){return std::pow(x,2);});
//find the square root of the sum of squares and check if it is less than or equal to the radius
return std::sqrt(std::accumulate(point.begin(), point.end(), 0, std::plus<int>())) <= radius;    
}
// Counts the number of lattice points inside the sphere( all points (x1 .... xn) such that xi is an integer )
// The algorithm: If the radius is a floating point value, first find the floor of the radius and cast it to 
// an integer. For example, if the radius is 2.43 then the only integer points we must check are those between
// -2 and 2. We generate these points by simulating n - nested loops using recursion and passing each point
// in to the boolean function isPointWithinSphere(...), if the function returns true, we add one to the count
// (we have found a lattice point on the sphere). 
int countLatticePoints(std::vector<int> &point, const double radius, const int dimension, int count = 0) {
const int R = static_cast<int>(std::floor(radius));
for(int i = -R; i <= R; i++) {
point.push_back(i);
if(point.size() == dimension){
if(isPointWithinSphere(point, radius)) count++;
}else count = countLatticePoints(point, radius, dimension, count);
point.pop_back();
}
return count;
}
int main(int argc, char ** argv) {
std::vector<int> vec {};
std::vector<std::thread> threads;
auto max_threads = std::thread::hardware_concurrency();
for(unsigned i = 0; i < max_threads; ++i)
threads.push_back(std::thread(countLatticePoints, vec, atof(argv[1]), atoi(argv[2])));
std::for_each(threads.begin(), threads.end(),  std::mem_fn(&std::thread::join));
return 0;
}

我正试图并行运行上述计算。基本上,我想调用函数countLatticePoints(vec, 1.05, 3),以便系统上运行计算并返回一个最终结果的线程数达到最大值。我很难设置这个。我所尝试的是让所有线程都加入我的计算,但我收到了以下非常不可理解的错误消息。

g++ nDimensionalSphere.cpp -o nDimensionalSphere -std=c++14 -pthread
In file included from /usr/include/c++/4.9/thread:39:0,
from nDimensionalSphere.cpp:6:
/usr/include/c++/4.9/functional: In instantiation of ‘struct std::_Bind_simple<int (*(std::vector<int>, double, int))(std::vector<int>&, double, int, int)>’:
/usr/include/c++/4.9/thread:140:47:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = int (&)(std::vector<int>&, double, int, int); _Args = {std::vector<int, std::allocator<int> >&, double, int}]’
nDimensionalSphere.cpp:56:92:   required from here
/usr/include/c++/4.9/functional:1665:61: error: no type named ‘type’ in ‘class std::result_of<int (*(std::vector<int>, double, int))(std::vector<int>&, double, int, int)>’
typedef typename result_of<_Callable(_Args...)>::type result_type;
^
/usr/include/c++/4.9/functional:1695:9: error: no type named ‘type’ in ‘class std::result_of<int (*(std::vector<int>, double, int))(std::vector<int>&, double, int, int)>’
_M_invoke(_Index_tuple<_Indices...>)
^ 

这是一个重要的编译错误:

/usr/include/c++/4.9/functional: In instantiation of ‘struct std::_Bind_simple<int (*(std::vector<int>, double, int))(std::vector<int>&, double, int, int)>’:

编译器检测到countLatticePoints接受对向量的引用,但正在传递实际向量。您可以通过使用std::ref传递对向量的引用来编译它,如下所示:

threads.push_back(std::thread(&countLatticePoints, std::ref(vec), atof(argv[1]), atoi(argv[2]), 0 /*the default parameter*/));

但这是一个糟糕的想法,因为现在所有线程都共享一个向量,而且由于向量不安全,你只会陷入灾难。

您可以更改countLatticePoints以接受实际向量,然后您就不再需要std::ref了。然后,函数获得自己的向量,这是线程安全的,但每个线程都会执行整个向量,这不是您想要的

所有这些的答案是向每个线程传递它自己的实际向量(而不是引用)以确保线程安全,但从迭代器对中构造每个向量,使其只包含一小部分项,从而使每个线程都获得不同的数据集。

还有其他问题,比如线程是如何连接的,但它们需要一个新问题,因为它们与您提出的问题无关。