#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;
}
私は上記の計算を並列に実行しようとしています。基本的には、システム上のスレッドの最大数が計算を実行して最終結果を1つ返すように、関数countLatticePoints(vec, 1.05, 3)
を呼び出したいと思います。私はこれを設定するのが難しいです。私が試したことは、すべてのスレッドを計算に参加させることですが、以下の非常に判読不能なエラーメッセージが表示されます。C++ STLマルチスレッド、並列計算での実行
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...>)
^
コンパイルエラーの他に、はるかに大きな問題があります。各スレッドは同じ 'std :: vector'に対して' push_back'()を試みます。 'std :: vector'はスレッドの安全性を保証するものではないため、未定義の動作になります。 –
@SamVarshavchikああ、ループの最後の 'pop_back'はさらに楽しいです:) – kfsone
ええ、この全体が救済可能な点をちょうど超えています。 –