我正在尝试使用openmp通过std :: set多线程循环.当我写下面的代码 -
#pragma omp parallel for
for (std::set<A>::const_iterator i = s.begin(); i != s.end(); ++i) {
const A a = *i;
operate(a);
}
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
error: invalid type for iteration variable 'i'
error: invalid controlling predicate
error: invalid increment expression.
Run Code Online (Sandbox Code Playgroud)
是否有另一种正确的方法来使用openmp迭代std容器?
我知道我可以使用int i和迭代0到s.size()迭代器或operator[]循环体,但这看起来不那么干净.
我的C++/OpenMP代码中有一个循环,如下所示:
#pragma omp parallel for
for(unsigned int i=0; i<count; i++)
{
// do stuff
}
Run Code Online (Sandbox Code Playgroud)
当我编译它(使用Visual Studio 2005)时,我收到以下错误:
error C3016: 'i' : index variable in OpenMP 'for' statement must have signed integral type
我知道发生错误的原因i是因为是无符号而不是签名,而更改i为签名会删除此错误.我想知道的是为什么这是一个错误?为什么不允许使用无符号索引变量?查看此错误的MSDN页面没有提供任何线索.
我是一个相当有经验的OpenMP用户,但我遇到了一个令人费解的问题,我希望有人可以提供帮助.问题是,一个简单的哈希算法对堆栈分配的数组表现良好,但对堆上的数组表现不佳.
下面的示例使用i%M(i模数M)来计算相应阵列元素中的每个第M个整数.为简单起见,假设N = 1000000,M = 10.如果N%M == 0,那么结果应该是bins []的每个元素都等于N/M:
#pragma omp for
for (int i=0; i<N; i++)
bins[ i%M ]++;
Run Code Online (Sandbox Code Playgroud)
数组bins []对每个线程都是私有的(我在之后对关键部分中所有线程的结果进行求和).
当在堆栈上分配bins []时,程序运行良好,性能与内核数量成比例缩放.
但是,如果bin []在堆上(指向bin []的指针在堆栈上),性能会急剧下降.这是一个重大问题!
我希望使用OpenMP将某些数据的binning(散列)并行化为堆数组,这是一个重大的性能影响.
绝对不是像所有线程试图写入同一内存区域那样愚蠢的东西.这是因为每个线程都有自己的bins []数组,结果对于堆栈和堆栈分配的bin都是正确的,并且单线程运行的性能没有差别.我使用GCC和英特尔C++编译器在不同的硬件(Intel Xeon和AMD Opteron)上重现了这个问题.所有测试都在Linux(Ubuntu和RedHat)上进行.
似乎没有理由将OpenMP的良好性能限制在堆栈数组中.
任何猜测?也许对线程的访问是通过Linux上的某种共享网关进行的?我该如何解决这个问题?
完整的程序如下:
#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
int main(const int argc, const char* argv[])
{
const int N=1024*1024*1024;
const int M=4;
double t1, t2;
int checksum=0;
printf("OpenMP threads: %d\n", omp_get_max_threads());
//////////////////////////////////////////////////////////////////
// Case 1: stack-allocated array
t1=omp_get_wtime();
checksum=0;
#pragma omp parallel
{ // Each openmp thread …Run Code Online (Sandbox Code Playgroud) 我想使用OpenMP以并行方式遍历std :: list中的所有元素.循环应该能够改变列表的元素.有一个简单的解决方案吗?当迭代器是随机访问迭代器时,似乎OpenMP 3.0支持并行for循环,但不是其他.无论如何,我更喜欢使用OpenMP 2.0,因为我无法完全控制哪些编译器可供我使用.
如果我的容器是矢量,我可能会使用:
#pragma omp parallel for
for (auto it = v.begin(); it != v.end(); ++it) {
it->process();
}
Run Code Online (Sandbox Code Playgroud)
我知道我可以将列表复制到矢量中,执行循环,然后将所有内容复制回来.但是,如果可能的话,我想避免这种复杂性和开销.
首先,我知道经常会问这种[类型]问题,所以让我先说一下我尽可能多地阅读,但我仍然不知道这笔交易是什么.
我已经并行化了一个巨大的外部for循环.循环迭代次数各不相同,通常在20-150之间,但是循环体做了大量的工作,需要大量的局部密集线性代数例程(例如,代码是源的一部分,而不是外部依赖) .在循环体内有1000多个调用这些例程的调用,但它们都完全相互独立,所以我认为它将是并行性的主要候选者.循环代码是C++,但它调用了许多用C编写的子程序.
代码看起来像这样;
<declare and initialize shared variables here>
#ifdef _OPENMP
#pragma omp parallel for \
private(....)\
shared(....) \
firstprivate(....) schedule(runtime)
#endif
for(tst = 0; tst < ntest; tst++) {
// Lots of functionality (science!)
// Calls to other deep functions which manipulate private variables only
// Call to function which has 1000 loop iterations doing matrix manipulation
// With no exaggeration, there are probably millions
// of for-loop iterations in this body, in the various functions …Run Code Online (Sandbox Code Playgroud) 我有一个关于openmp编译的问题.
如下代码:
#include <iostream>
#include <pthread.h>
#include <omp.h>
#include <semaphore.h>
#include <stack>
using namespace std;
sem_t empty,full;
stack<int> stk;
void produce(int i)
{
{
sem_wait(&empty);
cout<<"produce "<<i*i<<endl;
stk.push(i*i);
sem_post(&full);
}
}
void consume1(int &x)
{
sem_wait(&full);
int data=stk.top();
stk.pop();
x=data;
sem_post(&empty);
}
void consume2()
{
sem_wait(&full);
int data=stk.top();
stk.pop();
cout<<"consume2 "<<data<<endl;
sem_post(&empty);
}
int main()
{
sem_init(&empty,0,1);
sem_init(&full,0,0);
pthread_t t1,t2,t3;
omp_set_num_threads(3);
int TID=0;
#pragma omp parallel private(TID)
{
TID=omp_get_thread_num();
if(TID==0)
{
cout<<"There are "<<omp_get_num_threads()<<" threads"<<endl;
for(int i=0;i<5;i++)
produce(i);
}
else …Run Code Online (Sandbox Code Playgroud) 我想知道openacc和openmp之间的主要区别是什么.MPI,cuda和opencl怎么样?我理解openmp和mpi之间的区别,特别是关于共享和分布式内存的部分它们是否允许混合gpu-cpu处理设置?
两个数组的点积
for(int i=0; i<n; i++) {
sum += x[i]*y[i];
}
Run Code Online (Sandbox Code Playgroud)
不重用数据,因此它应该是一个内存绑定操作.因此,我应该能够从点积测量内存带宽.
使用代码 为什么 - 矢量化 - 循环 - 没有性能改进 我的系统带宽为9.3 GB/s.但是,当我尝试使用点积计算带宽时,我获得单个线程的速率的两倍以及使用多个线程的速率超过三倍(我的系统有四个核心/八个超线程).这对我没有意义,因为内存绑定操作不应该受益于多个线程.以下代码的输出如下:
Xeon E5-1620, GCC 4.9.0, Linux kernel 3.13
dot 1 thread: 1.0 GB, sum 191054.81, time 4.98 s, 21.56 GB/s, 5.39 GFLOPS
dot_avx 1 thread 1.0 GB, sum 191043.33, time 5.16 s, 20.79 GB/s, 5.20 GFLOPS
dot_avx 2 threads: 1.0 GB, sum 191045.34, time 3.44 s, 31.24 GB/s, 7.81 GFLOPS
dot_avx 8 threads: 1.0 GB, sum 191043.34, time 3.26 …Run Code Online (Sandbox Code Playgroud) OpenMP本身是否支持减少表示数组的变量?
这可能会像以下一样......
float* a = (float*) calloc(4*sizeof(float));
omp_set_num_threads(13);
#pragma omp parallel reduction(+:a)
for(i=0;i<4;i++){
a[i] += 1; // Thread-local copy of a incremented by something interesting
}
// a now contains [13 13 13 13]
Run Code Online (Sandbox Code Playgroud)
理想情况下,对于omp并行会有类似的东西,并且如果你有足够多的线程使它有意义,那么积累将通过二叉树发生.
我已经在Stackoverflow上读到,没有一个STL容器对于写入是线程安全的.但这在实践中意味着什么?这是否意味着我应该将可写数据存储在普通数组中?
我希望并发调用std::vector::push_back(element)可能会导致数据结构不一致,因为它可能需要调整向量的大小.但是这样的情况呢,不涉及调整大小:
1)使用数组:
int data[n];
// initialize values here...
#pragma omp parallel for
for (int i = 0; i < n; ++i) {
data[i] += func(i);
}
Run Code Online (Sandbox Code Playgroud)
2)使用`std :: vector``:
std::vector<int> data;
data.resize(n);
// initialize values here...
#pragma omp parallel for
for (int i = 0; i < n; ++i) {
data[i] += func(i);
}
Run Code Online (Sandbox Code Playgroud)
第一个实现是否真的比第二个更好a)在线程安全方面和b)在性能方面?我更喜欢使用std :: vector,因为我对C风格的数组不太熟悉.
编辑:我删除了#pragma omp atomic update保护写.