我有一个可以并行化的C++程序.我正在使用Visual Studio 2010,32位编译.
简而言之,该计划的结构如下
#define num_iterations 64 //some number
struct result
{
//some stuff
}
result best_result=initial_bad_result;
for(i=0; i<many_times; i++)
{
result *results[num_iterations];
for(j=0; j<num_iterations; j++)
{
some_computations(results+j);
}
// update best_result;
}
Run Code Online (Sandbox Code Playgroud)
由于每个some_computations()都是独立的(读取了一些全局变量,但没有修改全局变量),我并行化了内部for循环.
我的第一次尝试是使用boost :: thread,
thread_group group;
for(j=0; j<num_iterations; j++)
{
group.create_thread(boost::bind(&some_computation, this, result+j));
}
group.join_all();
Run Code Online (Sandbox Code Playgroud)
结果很好,但我决定尝试更多.
我试过OpenMP库
#pragma omp parallel for
for(j=0; j<num_iterations; j++)
{
some_computations(results+j);
}
Run Code Online (Sandbox Code Playgroud)
结果比boost::thread那些更差.
然后我尝试了ppl库并使用parallel_for():
Concurrency::parallel_for(0,num_iterations, [=](int j) { …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一些多线程代码来从DAQ设备读取并同时渲染捕获的信号:
std::atomic <bool> rendering (false);
auto render = [&rendering, &display, &signal] (void)
{
while (not rendering)
{std::this_thread::yield ();};
do {display.draw (signal);}
while (display.rendering ()); // returns false when user quits
rendering = false;
};
auto capture = [&rendering, &daq] (void)
{
for (int i = daq.read_frequency (); i --> 0;)
daq.record (); // fill the buffer before displaying the signal
rendering = true;
do {daq.record ();}
while (rendering);
daq.stop ();
};
std::thread rendering_thread (render);
std::thread capturing_thread (capture);
rendering_thread.join ();
capturing_thread.join …Run Code Online (Sandbox Code Playgroud) 我有两个版本的代码产生相同的结果,我试图只并行化嵌套for循环的内部循环.我没有得到太多的加速,但我没想到1对1,因为我只想并行化内循环.
我的主要问题是为什么这两个版本的运行时间相似?不是第二个版本的fork线程只有一次并且避免了i在第一个版本中每次迭代时启动新线程的开销吗?
第一个版本的代码在外部循环的每次迭代中启动线程,如下所示:
for(i=0; i<2000000; i++){
sum = 0;
#pragma omp parallel for private(j) reduction(+:sum)
for(j=0; j<1000; j++){
sum += 1;
}
final += sum;
}
printf("final=%d\n",final/2000000);
Run Code Online (Sandbox Code Playgroud)
使用此输出和运行时:
OMP_NUM_THREADS = 1
final=1000
real 0m5.847s
user 0m5.628s
sys 0m0.212s
Run Code Online (Sandbox Code Playgroud)
OMP_NUM_THREADS = 4
final=1000
real 0m4.017s
user 0m15.612s
sys 0m0.336s
Run Code Online (Sandbox Code Playgroud)
第二个版本的代码在外部循环之前启动一次线程(?)并像这样并行化内部循环:
#pragma omp parallel private(i,j)
for(i=0; i<2000000; i++){
sum = 0;
#pragma omp barrier
#pragma omp for reduction(+:sum)
for(j=0; j<1000; j++){
sum += 1;
}
#pragma omp single …Run Code Online (Sandbox Code Playgroud) 所以当我加载它时,我尝试运行一个名为BTYDplus的包我得到了这个警告
This data.table install has not detected OpenMP support. It will work but slower in single threaded mode.
我可以运行它没有OpenMP的,但它是非常缓慢的,所以我想通过下面这个教程安装的OpenMP
http://thecoatlessprofessor.com/programming/openmp-in-r-on-os-x/
但我在卡住Enabling R to Compile Code with OpenMP on OS X部分明确当我试图跑vim ~/.R/Makevars/.结果是"~/.R/Makevars/" Illegal file name.
关于如何告诉R使用GCC的任何建议?
我正在使用rand()函数生成0,1之间的伪随机数用于模拟目的,但是当我决定使我的C++代码并行运行时(通过OpenMP),我注意到rand()它不是线程安全的,也不是很均匀.
所以我转而使用在其他问题的许多答案中提出的(所谓的)更均匀的生成器.看起来像这样
double rnd(const double & min, const double & max) {
static thread_local mt19937* generator = nullptr;
if (!generator) generator = new mt19937(clock() + omp_get_thread_num());
uniform_real_distribution<double> distribution(min, max);
return fabs(distribution(*generator));
}
Run Code Online (Sandbox Code Playgroud)
但是我在我模拟的原始问题中看到了许多科学错误.既反对结果rand()也反对常识的问题.
所以我编写了一个代码,用这个函数生成500k随机数,计算它们的平均值并做200次并绘制结果.
double SUM=0;
for(r=0; r<=10; r+=0.05){
#pragma omp parallel for ordered schedule(static)
for(w=1; w<=500000; w++){
double a;
a=rnd(0,1);
SUM=SUM+a;
}
SUM=SUM/w_max;
ft<<r<<'\t'<<SUM<<'\n';
SUM=0;
}
Run Code Online (Sandbox Code Playgroud)
我们知道如果不是500k,我可以无限次地做它,它应该是一个值为0.5的简单线.但是有了500k,我们的波动将在0.5左右.
使用单个线程运行代码时,结果是可以接受的:
但这是2个线程的结果:
3个主题:
4个主题:
我现在没有我的8线程CPU,但结果甚至值得.
正如你所看到的,它们都不均匀,并且在平均值附近波动很大.
这个伪随机生成器线程也不安全吗?
或者我在某个地方犯了错误?
由于 c++17 std 库支持并行算法,我认为它是我们的首选,但在与tbband比较后openmp,我改变了主意,我发现 std 库要慢得多。
通过这个帖子,我想请教一下我是否应该放弃标准库的并行算法,而使用tbbor 的专业建议openmp,谢谢!
环境:
基准代码:
#include <algorithm>
#include <cmath>
#include <chrono>
#include <execution>
#include <iostream>
#include <tbb/parallel_for.h>
#include <vector>
const size_t N = 1000000;
double std_for() {
auto values = std::vector<double>(N);
size_t n_par = 5lu;
auto indices = std::vector<size_t>(n_par);
std::iota(indices.begin(), indices.end(), 0lu);
size_t stride = static_cast<size_t>(N / n_par) + 1;
std::for_each(
std::execution::par,
indices.begin(),
indices.end(),
[&](size_t index) {
int begin = index * …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用openMP并行化我的程序.该程序大量使用STL迭代器.这是说,是的OpenMP 3.0可以解决这个问题:
std::vector<int> N(2*N_max+1);
std::vector<int>::const_iterator n,m;
#pragma omp parallel for
for (n=N.begin(); n!=N.end(); ++n){
//Task to be in parallel
};
Run Code Online (Sandbox Code Playgroud)
但是我收到以下错误:
error: invalid controlling predicate
Run Code Online (Sandbox Code Playgroud)
我正在使用gcc 4.5.0,(4.4.0中实现的openMP3),我的构建字符串是:
g++ -O0 -g3 -Wall -c -fmessage-length=0 -fopenmp -MMD -MP
Run Code Online (Sandbox Code Playgroud) 在OpenMP中并行化多维尴尬并行循环的正确方法是什么?维度的数量在编译时是已知的,但是哪个维度是大的.他们中的任何一个可能是一,二或一百万.当然我不希望N omp parallel是一个N维循环......
思考:
问题在概念上很简单.只有最外层的"大"循环需要并行化,但循环维度在编译时是未知的并且可能会发生变化.
将动态设置omp_set_num_threads(1)和#pragma omp for schedule(static, huge_number)使某些环路并行化无操作?这会产生不良的副作用/开销吗?感觉像一个kludge.
在OpenMP规范(2.10,A.38,A.39)讲述整合及不符合要求的嵌套并行之间的差异,但没有提出解决这个问题的最好的办法.
可以重新排序循环,但可能会导致大量缓存未命中.展开是可能的,但不是重要的.还有另外一种方法吗?
这是我要并行化的内容:
for(i0=0; i0<n[0]; i0++) {
for(i1=0; i1<n[1]; i1++) {
...
for(iN=0; iN<n[N]; iN++) {
<embarrasingly parallel operations>
}
...
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢!
我有一个compute()使用OpenMP在其内部并行化矩阵乘法的函数
#pragma omp parallel for
Run Code Online (Sandbox Code Playgroud)
这个函数在循环中被多次调用 - 我想并行运行.在其他并行代码中运行并行代码会有任何问题吗?
这是在Ubuntu上编译的c ++.
当我尝试使用OpenMP并行化一些循环时,我正在解决一个更大的问题并遇到了一个bug.我用下面的一些更简单的代码重现了这个问题,这些代码模仿了我自己的代码.
问题是,当我运行程序时,它将随机进入某种无限循环/死锁(CPU为100%,但没有做任何事情).从我的测试中可以看出,其中一个线程试图计算矩阵矩阵产品,但由于某种原因从未完成.
我知道如果启用OpenMP,Eigen将使用OpenMP并行化矩阵 - 矩阵产品.我还在这之外添加另一个并行循环.但是,如果我通过定义EIGEN_DONT_PARALLELIZE禁用Eigen的并行化,则仍会出现此错误.
我在MacOS 10.6.8上使用gcc版本4.6.0 20101127和Eigen 3.0.4.
我无法弄清楚会出现什么问题......
#include <iostream>
#include <Eigen/Core>
using namespace std;
using namespace Eigen;
MatrixXd Test(MatrixXd const& F, MatrixXd const& G)
{
MatrixXd H(F.rows(), G.cols());
H.noalias() = F*G;
return H;
}
int main()
{
MatrixXd F = MatrixXd::Random(2,2);
MatrixXd G = MatrixXd::Random(2,2);
#pragma omp parallel for
for (unsigned int i = 0; i < 10000; ++i)
MatrixXd H = Test(F,G);
cout << "Done!" << endl;
}
Run Code Online (Sandbox Code Playgroud)