关闭

openMP讨论帖

1178人阅读 评论(0) 收藏 举报

[推荐] 【系列讲座】OpenMP 入门[问题点数:0,结帖人:intel_jeff]

  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
  • 结帖率:
楼主发表于:2008-05-12 16:48:04
OpenMP是一个业界的标准,很早以前就有了,只是近一段时间才逐渐热起来。我们可以在C/C++和Fortran使用OpenMP、很容易的引入多线程。


OpenMP目前的标准是2.5,3.0马上也要通过了。官方网站www.openmp.org上有你需要知道的一切信息,包括OpenMP规范文档。



下图是一个典型的OpenMP程序的示意图,我们可以看到它是由串行代码和并行代码交错组成的,并行代码的区域我们把它叫做“并行区”。主线程一旦进入并行区,就自动产生出多个线程,来并行的执行。



怎样在我们的代码中使用OpenMP呢?很简单,拿我们常用的C/C++代码来说,只需要插入如下pragma,然后我们选择不同的construct就可以完成不同的功能。



(待续。。。)
 
 
回复次数:99
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#1楼 得分:0回复于:2008-05-12 16:54:03
首先,我们来看一下如何创建一个并行区:增加一行代码#pragma omp parallel,然后用花括号把你需要放在并行区内的语句括起来,并行区就创建好了。并行区里每个线程都会去执行并行区中的代码。



那么怎么来控制并行区中线程的数量呢?默认情况下,并行区内线程数=系统中核的个数。如果你需要修改,方法之一是设置环境变量。



下一节我们将看一个最简单的OpenMP代码,看看并行区是怎样工作的。


(待续。。。)
 
  • Kaile用户头像
  • Kaile
  • (领头羊)
  • 等 级:
#2楼 得分:0回复于:2008-05-12 17:15:04
没有了?
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#3楼 得分:0回复于:2008-05-13 11:16:47
我们来看一个最简单的OpenMP程序例子:
===================================
#include <stdio.h>

int main() {
  #pragma omp parallel
  {
  int i;
  printf("Hello World/n");
  for(i=0;i<6;i++)
  printf("Iter:%d/n",i);
  }
  printf("GoodBye World/n");
}
===================================


我们现在用Intel编译器来编译这个小程序,当然你也可以用VS2005来编译。

我们可以看到编译器在没有加 /Qopenmp 开关的时候,会忽略掉所有openmp pragma。我们可以利用这个特性来检查你的代码在串行的时候运行

结果是否正确。
D:/test>icl /nologo HelloWorlds.c
HelloWorlds.c
HelloWorlds.c(4): warning #161: unrecognized #pragma
  #pragma omp parallel
  ^


串行代码执行的结果如下:
D:/test>HelloWorlds.exe
Hello World
Iter:0
Iter:1
Iter:2
Iter:3
Iter:4
Iter:5
GoodBye World


下面我们加上 /Qopenmp 开关重新编译,我们会看到编译器给出提示说已经把并行区给做并行化了。
D:/test>icl /nologo /Qopenmp HelloWorlds.c
HelloWorlds.c
HelloWorlds.c(4): (col. 5) remark: OpenMP DEFINED REGION WAS PARALLELIZED.


我的机器是4核,运行这个程序就打印出如下结果。我们可以看到每次运行打印出来的东西顺序是不一定的,这个符合多线程程序的特性。在4

核的机器上,并行区内就产生了4个线程同时执行for循环打印,默认线程数=核的个数。
D:/test>HelloWorlds.exe
Hello World
Iter:0
Iter:1
Iter:2
Iter:3
Iter:4
Iter:5
Hello World
Iter:0
Hello World
Iter:0
Iter:1
Iter:2
Iter:3
Iter:4
Iter:5
Hello World
Iter:0
Iter:1
Iter:1
Iter:2
Iter:2
Iter:3
Iter:3
Iter:4
Iter:4
Iter:5
Iter:5
GoodBye World


我们来修改一下线程的数量,然后再运行一下代码,看下运行结果
D:/test>set OMP_NUM_THREADS=2
D:/test>HelloWorlds.exe
Hello World
Iter:0
Iter:1
Iter:2
Iter:3
Iter:4
Iter:5
Hello World
Iter:0
Iter:1
Iter:2
Iter:3
Iter:4
Iter:5
GoodBye World

D:/test>


现在我们对并行区有了一定的了解,并行区里每个线程执行的代码是一样的,做的事情似乎也是一样的,但是实际工作中,我们希望把一部分

工作分配给不同线程来做,这应该怎么实现呢?请看下节。


(待续。。。)
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#4楼 得分:0回复于:2008-05-13 16:22:00
我们近期将推出更多的 系列讲座,大家希望看到我们介绍什么内容可以提出来,当然主要是围绕Intel的软件工具产品。如果大家认为有比讲座更好的方式,也请告诉我们,谢谢!
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#5楼 得分:0回复于:2008-05-14 16:33:33
下面我们来看一个新的openmp语句
#pragma omp for
使用这个语句,我们就可以把一个for循环的工作量(例如:1...N)分配给不同线程。这个语句后面必须紧跟一个for循环,他只能对循环的工作量进行划分、分配。



看下面这个例子,0...11的工作量被平均分配给了3个线程。当3个线程都完成了各自的工作后,程序才继续往下执行。



写2行openmp pragma实在有些麻烦,我们可以把2行或多行openmp pragma合并未一行,这样好多了,是吧。



(待续。。。)
 
  • abuion用户头像
  • abuion
  • (abuion)
  • 等 级:
#6楼 得分:0回复于:2008-05-14 18:13:46
全英文!
用点通俗点的来介绍一下你的openmp嘛
是一种语言还是像xml之类的一种业界标准
 
#7楼 得分:0回复于:2008-05-14 19:20:10
能问个问题么

多线程对可分的计算是很好的

但是对大量内存的访问是不是也能提速呢,

比如我做图像处理,做一个gauss光滑,要访问周围点然后来计算,并且前后不相关,可以分多线程,计算方面肯定提速了

但是对不同线程的内存访问是不是也分别用各自的缓存

似乎这个问题和多核的cpu是共享缓存,还是各自独立缓存有关,
 
#8楼 得分:0回复于:2008-05-14 22:47:44
引用 6 楼 abuion 的回复:
全英文!
用点通俗点的来介绍一下你的openmp嘛
是一种语言还是像xml之类的一种业界标准


是业界的标准, 详细的规范请见 http://www.openmp.org
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#9楼 得分:0回复于:2008-05-16 11:24:53
引用 7 楼 youxia000 的回复:
能问个问题么 

多线程对可分的计算是很好的 

但是对大量内存的访问是不是也能提速呢, 

比如我做图像处理,做一个gauss光滑,要访问周围点然后来计算,并且前后不相关,可以分多线程,计算方面肯定提速了 

但是对不同线程的内存访问是不是也分别用各自的缓存 

似乎这个问题和多核的cpu是共享缓存,还是各自独立缓存有关,


最好能利用好缓存,尽量把相近的点一起做。你可以尝试不同的划分方法,比如把大图切割成 n x n 的小块,每个线程做一个小块;或者每个线程做1行,即线程1做第1,n+1,2n+1行,第2个线程做第2,n+2,2n+2行,n为线程数。多试试几个方法,应该有一个最适合你的方法。
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#10楼 得分:0回复于:2008-05-16 14:12:34
==================================
  数据环境(Data Environment)
==================================

OpenMP属于共享内存的编程模型。在我们的多线程代码中,大部分数据都是可以共享的。共享内存给我们程序中数据的共享带来了极大的便利。因此在默认情况下,OpenMP将全局变量、静态变量设置为共享属性。

但是,还是有些变量需要是每个线程私有的,也就是每个线程有这些变量的独立拷贝,这样每个线程在使用这些变量时不会相互影响。需要私有的变量包括:



我们可以通过如下方法来改变OpenMP的变量默认属性,你可以把它设置为共享(shared)或无。也可以单独改变某几个变量的属性,把他们设置为shared或private。



看看下面这个例子,循环变量i默认为私有,因为x和y是中间变量,应该设置为私有,否则线程之间的x,y会互相影响。



再看看这个例子。变量sum定义在并行区之外,所以默认为共享,这个例子里又写了shared(sum),没错,但是实际上是罗嗦了。那么这个例子里有什么错误呢?



如果以前做过多线程开发的话应该能看出来,sum不应该是共享的,但是设置为私有的也不对。我们的做法应该是将sum保护起来,防止多个线程同时对sum进行写操作。我们可以使用OpenMP的临界区来对sum进行保护。



(待续。。。)
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#11楼 得分:0回复于:2008-05-22 16:15:47
欢迎大家有问题随时提问。
 
  • Kaile用户头像
  • Kaile
  • (领头羊)
  • 等 级:
#12楼 得分:0回复于:2008-05-28 13:19:58
我是OPENMP新手,对于上一段代码,我还是有困惑:

设置了critical以后, 

sum+= ... 这句话说明多个线程不同时作加法,但是还是每个线程做N次加法, 这样N*线程数的结果与单线程的N次结果会大相径庭,对吗?

有什么办法既提高速度又不改变逻辑了?
 
  • Kaile用户头像
  • Kaile
  • (领头羊)
  • 等 级:
#13楼 得分:0回复于:2008-05-28 14:43:45
我上面的理解不对,


#pragma omp parallel for  
这句话应该是 把for循环分为N部分,分配给每个独立的线程。

因为 

sum+= N这一句话 牵涉到读 sum,所以不能设置为shared.  

我这样理解对吗?
 
  • Kaile用户头像
  • Kaile
  • (领头羊)
  • 等 级:
#14楼 得分:0回复于:2008-05-28 21:20:47
上面的代码如果这样改:

  #pragma omp for reduction(+: sum)  
 for(int i = 0; i <N; i++)
{
sum += a[i] + b[i];
}

是不是和范例的代码等价了?
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#15楼 得分:0回复于:2008-05-29 11:13:53
引用 13 楼 Kaile 的回复:
我上面的理解不对, 


#pragma omp parallel for 
这句话应该是 把for循环分为N部分,分配给每个独立的线程。 

因为  

sum+= N这一句话 牵涉到读 sum,所以不能设置为shared. 

我这样理解对吗?


昨天本想回你12楼的贴的,结果及其出问题了。今天上来一看,你已经自己解决了这个问题了。鼓励一下!
不错,你这个分析的完全正确。
 
  • Kaile用户头像
  • Kaile
  • (领头羊)
  • 等 级:
#16楼 得分:0回复于:2008-05-29 15:29:36
谢谢及时回复。那么14楼的分析有没有问题了?问题在哪里?
 
  • Kaile用户头像
  • Kaile
  • (领头羊)
  • 等 级:
#17楼 得分:0回复于:2008-05-29 15:42:48
#pragma omp parallel for
for (i=0;i<MAX;i++) {
for (j=0;j<MAX;j++) {
t[i][j]=FALSE;
}
}


还有,象上面这个语句,i 是私有的, j 是shared,运行起来会不会有问题了?
 
#18楼 得分:0回复于:2008-05-29 15:56:13
引用 17 楼 Kaile 的回复:
#pragma omp parallel for
for (i=0;i <MAX;i++) {
for (j=0;j <MAX;j++) {
t[i][j]=FALSE;
}
}

还有,象上面这个语句,i 是私有的, j 是shared,运行起来会不会有问题了?



并行区(Parallel Region)内, 未经声明, 所有的变量都是共享的, 只有一个例外
 
#19楼 得分:0回复于:2008-05-29 16:03:09
引用 16 楼 Kaile 的回复:
谢谢及时回复。那么14楼的分析有没有问题了?问题在哪里?


没有问题, 这是OpenMP提供的累加归约(Reduction)操作. 另外, 还可以支持乘, 逻辑运算等归约操作
 
#20楼 得分:0回复于:2008-05-29 16:14:44
引用 7 楼 youxia000 的回复:
能问个问题么

多线程对可分的计算是很好的

但是对大量内存的访问是不是也能提速呢,

比如我做图像处理,做一个gauss光滑,要访问周围点然后来计算,并且前后不相关,可以分多线程,计算方面肯定提速了

但是对不同线程的内存访问是不是也分别用各自的缓存

似乎这个问题和多核的cpu是共享缓存,还是各自独立缓存有关


在新的Core 微架构中, 采用了一个叫做 "Intel Advanced Smart Cache" 的技术

Intel Advanced Smart Cache is a multi-core optimized cache that improves performance and efficiency by increasing the probability
that each execution core of a dual-core processor can access data from a higher-performance, more-efficient cache subsystem.

To accomplish this, Intel Core microarchitecture shares the Level 2 (L2) cache between the cores. This better optimizes cache  
resources by storing data in one place that each core can access. By sharing L2 cache between each core, Intel Advanced Smart  
Cache allows each core to dynamically use up to 100 percent of available L2 cache. Threads can then dynamically use the required  
cache capacity. As an extreme example, if one of the cores is inactive, the other core will have access to the full cache.  
Intel Advanced Smart Cache enables very efficient sharing of data between threads running in different cores. It also enables  
obtaining data from cache at higher throughput rates for better performance. Intel Advanced Smart Cache provides a peak transfer
rate of 96 GB/sec (at 3 GHz frequency)

这篇白白书中有详细的说明: http://download.intel.com/technology/architecture/sma.pdf
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#21楼 得分:0回复于:2008-05-29 16:56:32
引用 17 楼 Kaile 的回复:
#pragma omp parallel for  
for (i=0;i <MAX;i++) {  
for (j=0;j <MAX;j++) {  
t[i][j]=FALSE;  
}  
}  


还有,象上面这个语句,i 是私有的, j 是shared,运行起来会不会有问题了?  


会有问题的,你需要将j声明为私有,或者在并行去内声明变量j。
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#22楼 得分:0回复于:2008-05-29 17:12:54
我们可以给临界区命名,在下面例子中,如果我们不给临界区命名,在任一时刻,只能有一个线程调用consum函数。而我们给临界区命名后,任一时刻可以有最多2个线程在调用consum函数(1个调用 consum(B, &R1),另一个调用 consum(A, &R2)。这在这2句语句可以同时执行的情况下,我们通过临界区命名来尽可能减少线程等待时间。



归约(Redunction)是个很有用的功能,可以简化我们的编程,op代表一个操作,list是执行这个操作的一个或多个变量。



我们再看刚才上面的例子就清楚了。我们对sum这个变量使用归约操作,操作符是+。这样的话,每个线程就会有一个私有的sum变量,当所有线程的计算完成后,每个线程的私有的sum的值将被用“+”归约成一个总的sum,即 线程1的sum + 线程2的sum + ... + 线程n的sum -> 总的sum,这个总的sum值将被带出并行区并赋给全局的那个sum变量,因此,当这个并行区的代码执行完以后,我们的sum变量的值就是我们期望得到的值了。
是不是比前面用临界区的方法要好得多、代码也会快得多呢?



下图是归约支持的操作符:



好了,来给大家做个小作业。下面代码是一个串行的求Pi的代码,使用的是积分的办法。请大家把这个代码用OpenMP来做并行化。



(待续。。。)
 
  • Kaile用户头像
  • Kaile
  • (领头羊)
  • 等 级:
#23楼 得分:0回复于:2008-05-29 21:12:34
我来试试:

#include <omp.h>

static long num_steps = 100000;
double step, pi;
void main()
{

int i;  
double x, sum = 0.0;
step = 1.0/ (double) num_steps;

#pragma omp parallel for private(x) reduction(+:sum)
for(i=0; i< num_steps; i++)
{
x = ( i + 0.5)*step;
sum = sum + 4.0/(1.0+ x*x);
}
pi = step * sum;
printf("Pi = %f/n"),pi);
}
 
  • Kaile用户头像
  • Kaile
  • (领头羊)
  • 等 级:
#24楼 得分:0回复于:2008-06-02 15:50:57
#pragma omp parallel for  
for(int i = 0; i< 20;i++)
{
if(i> 4)
break;
}


在学习OpenMP中,发现这样的break语句不能在这里用,如果循环中有这种逻辑,如何处理?
 
  • Kaile用户头像
  • Kaile
  • (领头羊)
  • 等 级:
#25楼 得分:0回复于:2008-06-02 15:54:03
我在单核心的机器上测试,如果加上

#pragma omp parallel sections

或者:


#pragma omp parallel for reduction(+:sum)
二种语句,性能会急剧下降。

如果只加 #pragma omp parallel for
性能不变化。


请问这种情况是正常的吗?
 
#26楼 得分:0回复于:2008-06-02 16:29:21
引用 25 楼 Kaile 的回复:
我在单核心的机器上测试,如果加上

#pragma omp parallel sections

或者:


#pragma omp parallel for reduction(+:sum)
二种语句,性能会急剧下降。

如果只加 #pragma omp parallel for
性能不变化。


请问这种情况是正常的吗?



请先考虑正确性, 再考虑性能
 
  • Kaile用户头像
  • Kaile
  • (领头羊)
  • 等 级:
#27楼 得分:0回复于:2008-06-02 16:32:03
当然是原来的逻辑没有改变了。
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#28楼 得分:0回复于:2008-06-04 11:09:31
引用 24 楼 Kaile 的回复:
#pragma omp parallel for 
for(int i = 0; i < 20;i++) 

if(i> 4) 
break; 



在学习OpenMP中,发现这样的break语句不能在这里用,如果循环中有这种逻辑,如何处理? 


这样的循环是不能并行的,你需要改写你的代码(如果可能的话),至于怎么改写就要看具体情况了。
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#29楼 得分:0回复于:2008-06-04 11:13:02
引用 25 楼 Kaile 的回复:
我在单核心的机器上测试,如果加上 

#pragma omp parallel sections 

或者: 


#pragma omp parallel for reduction(+:sum) 
二种语句,性能会急剧下降。 

如果只加 #pragma omp parallel for 
性能不变化。 


请问这种情况是正常的吗? 


sections 和 reduction 实际上的代码实现很简单,没有特别复杂的东西(正如我前面介绍reduction原理时说的)。在程序逻辑相同的情况下,应该不会大幅度降低性能。你的测试代码能否贴出来看看?
 
  • Kaile用户头像
  • Kaile
  • (领头羊)
  • 等 级:
#30楼 得分:0回复于:2008-06-13 09:59:58
前段时间比较忙,这2天开始研究这个问题。

因为我做得是一个棋牌程序,里面有三重循环,体内还有一个递归函数。我估计是循环,递归不断创建,析构线程导致性能下降,因此做了一个测试程序,请intel的大侠帮助看看。


void CopenmptestDlg::OnBnClickedButton1()
{
m_nCount = 0;
m_nValue = 0;

int nTick1 = GetTickCount();
for(int i = 0; i< 20;i ++)
{
for (int j=0; j< 20; j++)
{
for (int k=0; k< 20 ;k ++)
{
qs(m_nCount);
}
}
}
int nTick2 = GetTickCount();

ATLTRACE2(traceAppMsg, 0, "Value is %d, Tick count is %d/n", m_nValue, nTick2 - nTick1);
}


int CopenmptestDlg::qs(int count)
{
count ++;
if (count > 20)
return m_nValue;
int v1 = 0,v2=0 ;
#pragma omp parallel sections  
{
#pragma omp section
v1 += 10;
#pragma omp section
v2 += 20;
}
m_nValue += v1 + v2;

qs(count);

return m_nValue;


}

很简单的测试,对话框上一个按钮,按一下进入循环体,执行一个递归函数。

openmp 的section段也很简单,最后输出执行时间,但使用不使用OPENMP的结果让人大跌眼镜:

Value is 4800000, Tick count is 3828 //使用openmp sections

Value is 4800000, Tick count is 16 // 不使用

看来逻辑没问题,就是性能下降太厉害。

请教大侠这种情况如何是好?

 
  • Kaile用户头像
  • Kaile
  • (领头羊)
  • 等 级:
#31楼 得分:0回复于:2008-06-13 10:43:16
感觉是不是粒度分得太细,线程的开销已经大于多线程并行带来的好处,加上多重循环的累积,造成性能下降厉害。

有没有办法初始化线程,以后不动态创建和析构,这样是不是减少损耗?
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#32楼 得分:0回复于:2008-06-16 14:22:47
同意Kaile的看法,粒度太细了,应该尽可能在外层的循环用omp parallel for来做多线程化
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#33楼 得分:0回复于:2008-06-16 14:44:06
================================================
  OpenMP中工作量的划分与调度
================================================

前面我看到在使用工作量共享(work-sharing)这种方式的时候,工作量是自动给我们划分好并分配给各个线程的。下面,我们来看看如何来控制工作量的划分与调度。



如上图所示,工作量的划分与调度有3种方式:
1、静态:把循环的迭代按照每x次(x=chunk)迭代分为一块,这样你的总工作量就被划分成了n/x块(n为迭代次数、循环次数),然后将这些块按照轮转法依次分配给各个线程。举个例子:比如我们有100次迭代,x=chunk=4,那么我们的工作就被分为25块,假设我们有2个线程可以做工作,那么线程1分到的块是1,3,5,7....,25,线程2分到的块是2,4,6,...,24;
2、动态:迭代分块方法同上,但是工作块被放到一个队列中,每个线程每次拿一块,做好了才能到队列里去拿下一块;
3、Guided:这个方式是动态方式的改进。在这个方式里,分块的x是不固定的,一开始块的大小(x)比较大,随着剩余工作量的减小,块的大小也随之变小。

我们总结一下每种方式适合什么样的工作量
静态方式:比较适合每次迭代的工作量相近(主要指工作所需时间)的情况
动态方式:比较适合每次迭代的工作量非常不确定的情况
Guided方式:类似动态方式,但是队列相关的开销会比动态方式小


下面我们看一个例子:
#pragma omp parallel for schedule (static, 8)
for( int i = start; i <= end; i += 2 )
{
if ( TestForPrime(i) ) gPrimesFound++;
}


在这个例子中,如果start=3,那第一块就={3,5,7,9,11,13,15,17}
 
  • Kaile用户头像
  • Kaile
  • (领头羊)
  • 等 级:
#34楼 得分:0回复于:2008-06-29 21:28:50
还没有新内容吗?


更新能否快一些。
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#35楼 得分:0回复于:2008-07-02 13:34:49
好的,前些时间有些忙,希望今天能更新,谢谢~ ^_^
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#36楼 得分:0回复于:2008-07-02 14:33:29
================================================  
  另外几个OpenMP Construct  
================================================  

下面我们来看一看Parallel Section,其实看看下面的图片就知道了,我们可以定义多个section,让这些section并行的执行。下面的例子是我们有足够的线程来同时执行这3个section,如果我们只有2个线程,情况会是怎样呢?

如果只有2个线程,那么肯定得有1个线程要比另一个线程勤劳一点,执行2个section了。
在使用Parallel Section时需要注意的是,每个section的工作之间应该是相互独立、没有依赖关系的。如果不满足这个要求的话,就不要对他们用并行了。


下面再介绍2个有可能会用到的OpenMP construct。
1、single:有时候在并行区里,我们希望有部分代码只能执行一次,也就是说只有一个线程去执行这部分代码。如下面的例子,ExchangeBoundaries() 这句语句前面我们加上 #pragma omp single ,就保证只有一个线程去执行它。同时在single后面会有一个隐含的障碍(implicit barrier)。我们后面会具体介绍障碍这个概念。

  #pragma omp parallel
  {
  DoManyThings();
  #pragma omp single
  {
  ExchangeBoundaries();
  } // threads wait here for single
  DoManyMoreThings();
  }

2、master:master跟single很类似。在下面例子中,只有主线程会去执行 ExchangeBoundaries() 这条语句。但是master没有隐含的障碍,因此如果其他线程遇到 #pragma omp master,就会跳过去,直接执行master后面的语句。

  #pragma omp parallel
  {
  DoManyThings();
  #pragma omp master
  { // if not master skip to next stmt
  ExchangeBoundaries();
  }
  DoManyMoreThings();
  }



(待续~~~)
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#37楼 得分:0回复于:2008-07-02 14:50:27
================================================  
  障 碍
================================================  

在我们前面介绍过的OpenMP Construct,如parallel, for, single,他们自身都带有隐含的障碍。我们来看一下前面出现过的一个例子:


在这个例子里面,线程1做0-3的迭代,线程2做4-7的迭代,线程3做8-11的迭代,如果每次迭代的工作量不同,那么线程1、2、3完成他们各自的工作所需的时间是不同的,也就是说,某个线程可能比另外2个线程提前完成工作,但是这个线程不能继续往下走去执行并行区后面的工作,因为#pragma omp for里面带了隐含的障碍,这个障碍的意思就是说,所有的线程做完了自己的工作后必须在这里等,直到所有的线程都完成了各自的工作,大家才能往下走。汇编里的memory fence与这个有点神似。

为什么这些construct要带了个隐含的障碍呢?障碍不是让程序执行速度变慢了吗?因为它怕你程序里面后面的代码对这块代码有依赖关系,如果这块代码的工作没完成就去执行后面的代码,可能会引起错误。

那如果你后面的代码对这块代码没有依赖,可以用 nowait 来把这个隐含的障碍给去掉。比如:

例子1:
C/C++ code
#pragma omp for nowait for(...) {...};



例子2:
C/C++ code
#pragma single nowait { [...] }



例子3:
C/C++ code
#pragma omp for schedule(dynamic,1) nowait for(int i=0; i<n; i++) a[i] = bigFunc1(i); #pragma omp for schedule(dynamic,1) for(int j=0; j<m; j++) b[j] = bigFunc2(j);
 
  • Kaile用户头像
  • Kaile
  • (领头羊)
  • 等 级:
#38楼 得分:0回复于:2008-07-03 08:25:50
我看别的资料没有你解释得这么详细的,no wait我一直不知道怎么用,现在明白了。
 
#39楼 得分:0回复于:2008-07-04 12:40:25
学习]
 
#40楼 得分:0回复于:2008-07-04 13:32:14
路过,顶
 
  • xiao7cn用户头像
  • xiao7cn
  • (FriedChicken)
  • 等 级:
#41楼 得分:0回复于:2008-07-04 17:39:08
眼泪哗哗的~~
 
#42楼 得分:0回复于:2008-07-05 10:15:39
榜样啊。。学习中。。顶。
 
  • ewqtan用户头像
  • ewqtan
  • (学习)
  • 等 级:
#43楼 得分:0回复于:2008-07-05 11:05:35
 
  • e_bot用户头像
  • e_bot
  • (挖坟工Never Mind t)
  • 等 级:
#44楼 得分:0回复于:2008-07-07 19:27:14
打酱油路过
看看
 
#45楼 得分:0回复于:2008-07-08 17:19:52
谢谢
 
#46楼 得分:0回复于:2008-07-08 20:59:12
***************************************************************************  

思想决定行动,行动决定习惯,习惯决定命运.  
程序员在深圳QQ群,交流产生思想碰撞.  

部份专业群:  
程序员在深圳c++群15195967  
程序员在深圳英语学习群:23864353  
程序员在深圳c++Ⅱ17409451  
程序员在深圳嵌入式开发群37489763  
程序员在深圳移动开发群31501597  
程序员在深圳创业群33653422  

部份高级程序员群:  
高级群I:17538442  
高级群II:7120862  

部份初、中级程序员群:  
第三群:2650485  
第五群:29537639  
第四群:28702746  
第六群:10590618  
第七群:10543585  
第八群:12006492  
第九群:19063074  
第十群:2883885  
第十一群:25460595  
第十二群:9663807  

深圳程序员QQ群联盟成立三年多,拥有三十个以上的QQ群,人数超二千多人,大量经验丰富的老手,成员从业于大公司(如微软、IBM,SUN,华为  

)、来自国内著名高校和研究院成员,和有丰富实践经验的高级程序员、系统分析员(包括参加过上亿元的项目的架构师),有很热爱技术的成员  

(包括自己写操作系统),还有少数女程序员。推荐:深程高级群I:17538442 深程高级群II:7120862 (深程高级群不欢迎新手,如果在深圳,月薪  

6K以下的别加入) c++:15195967 mobile:31501597嵌入式:37489763   
——————————————————————————————————————————  
如果你不是第一次看到此广告,说明我们最近T了一些人,因为我们要不断提升群的质量,保证名副其实.  
-------------------------------------------------------------------------------------  
在通过电邮、新闻组或者聊天室提出技术问题前,检查你有没有做到:  
  1. 通读手册,试着自己找答案。  
  2. 在FAQ里找答案(一份维护得好的FAQ可以包罗万象:)。  
  3. 在网上搜索(个人推荐google~)。  
  4. 向你身边精于此道的朋友打听。  
我想我们首先应该*自己解决问题,然后才是问!  

*****************************************************************************  
 
#47楼 得分:0回复于:2008-07-08 23:32:41
不懂。。。。。。。。。。MARK
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#48楼 得分:0回复于:2008-07-11 11:22:26
================================================  
  介绍几个OpenMP API  
================================================  

在大多数情况下,我们不会用到OpenMP API。一般只有在调试和某些情况下,才需要用到API。

如果你需要使用 OpenMP API,记得先包含OpenMP头文件
C/C++ code
#include <omp.h>


最常用的2个API是:
C/C++ code
int omp_get_thread_num(void); int omp_get_num_threads(void);


在并行区里调用omp_get_thread_num返回的是当前线程的线程ID,一般是0到(N-1),N是并行区里的总线程数。
在并行区里调用omp_get_num_threads返回的是并行区里的总线程数。

使用这2个API,我们可以只用 #pragma omp parallel 就实现每个线程完成循环中不同的迭代。比如我们有这样一段代码,怎样在不使用 #pragma omp parallel for 的情况下,改写代码、把工作量划分给各个线程呢?
C/C++ code
#pragma omp parallel { for(i=0;i<N;i++) { c[i] = a[i] + b[i]; } }
 
#49楼 得分:0回复于:2008-07-11 17:00:32
刚开始学习OpenMP,谢谢指教。

#pragma omp parallel  
{
  for(i=0;i<(N/omp_get_num_thread()+1);i++)
  {
  int j = i * omp_get_num_thread() + omp_get_thread_num();
  if(j < N)
  {
  c[j]= a[j] + b[j];
  }
  }
}
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#50楼 得分:0回复于:2008-07-16 14:01:44
引用 49 楼 wwwquzhinet 的回复:
刚开始学习OpenMP,谢谢指教。 

#pragma omp parallel 

for(i=0;i <(N/omp_get_num_thread()+1);i++) 

int j = i * omp_get_num_thread() + omp_get_thread_num(); 
if(j < N) 

c[j]= a[j] + b[j]; 





工作量划分的要求做到了,但是效率还不够高哦。
 
#51楼 得分:0回复于:2008-07-18 10:14:07
咨询几个问题:

我用VS2005编写了一个多线程应用程序P,运行时至少运行2个线程;
这个应用程序中,我调用了一个C语言的库cLib;
我想在这个cLib 中添加一些OpenMP的指令,以加快多核计算机上的程序速度。

/********************************************
机器:IBM T61
CPU: Intel Core(TM)2 Duo CPU T7500 @2.00GHz
内存:1G
OS: WindowsXP Sp2
*********************************************/

第一个问题是:我发现,如果 cLib 是静态库,则cLib中的平行区域肯定是按照单核处理的。
按照 http://msdn.microsoft.com/en-ca/magazine/cc163717.aspx 的说法,“Note that Visual C++ does not support static linking of  
the OpenMP runtime”,这句话是不是说明,如果cLib使用静态链接库,则编译出来的库,不支持多核指令?如果使用Intel的编译器一样吗?

第二个问题:我将cLib编译成动态链接库,通过打印文件,我发现他确实是双核并行处理的。但是,并行处理部分的执行时间变化很大,如果不用OpenMP指令,则大约是 22ms,最大最小相差2ms左右;如果用了openMP指令,则执行时间变化很大,最慢的23ms也就是和单核一样,最快的15ms。
如果我在任务管理器中,强制设置应用程序只用一个核,则执行时间能稳定在17ms左右,但是偶然也有30多ms的。

也就是说,windowsXP下多核计算机,
自动对多线程程序多核并行处理的效率 < 强制让一个核处理多线程,但是多线程中的主要部分多核并行运算的效率
我这样理解对吗?

我要怎么做才能在多线程程序中使用OpenMP提高性能呢?
谢谢
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#52楼 得分:0回复于:2008-07-18 16:06:18
那句话是说MS的OpenMP库必须要动态链接,不可以静态链接,因为他们不提供OpenMP的静态库。Intel编译器10.1默认使用Intel的OpenMP库(可以做静态链接),你可以/Qopenmp-lib这个开关让Intel编译器选择使用Intel的OpenMP库还是用MS的OpenMP库。另外顺便说一下,从Intel编译器11.0开始,将默认使用MS的OpenMP库,以便可以跟MS编译器混合编译一个OpenMP项目,即:一个OpenMP的项目中,一部分文件用Intel编译器编译、另一部分用MS编译器编译,最后链接到一起。
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#53楼 得分:0回复于:2008-07-18 16:13:20
第2个问题,多线程的调度是由OS负责的,你测到的时间变化较大估计是受到了系统其他应用的影响,也可能你的并行代码有IO相关的操作。通常情况下,我们不需要去关心OS如何调度线程,OS的调度多半都是比较合适的。
 
  • ewqtan用户头像
  • ewqtan
  • (学习)
  • 等 级:
#54楼 得分:0回复于:2008-08-04 19:43:07
不懂??????
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#55楼 得分:0回复于:2008-08-07 15:24:44
下面再介绍几个数据环境相关的construct。前面我们看过了private, public,现在我们来看另外3个。


1、firstprivate:变量属性为private,同时每个线程的这个变量的初始值为全局变量的值。比如下面例子中,我们先给全局变量incr设置了一个值0,然后再并行区,每个线程都有自己的incr,而这些incr的初始值也为0(与并行区之前的全局量incr的值一致)。
C/C++ code
incr=0; #pragma omp parallel for firstprivate(incr) for (I=0;I<=MAX;I++) { if ((I%2)==0) incr++; A(I)=incr; }



2、lastprivate:当退出并行区时,最后一次迭代内的lastprivate变量的值将被带出并行区赋给全局的同名变量。在下面例子中,i循环的最后一次迭代中的x的值将被赋给全局的x,所以退出并行区后,全局量x被赋值了。
C/C++ code
void sq2(int n, double *lastterm) { double x; int i; #pragma omp parallel #pragma omp for lastprivate(x) for (i = 0; i < n; i++){ x = a[i]*a[i] + b[i]*b[i]; b[i] = sqrt(x); } lastterm = x; }



3、threadprivate:用于指定某变量为线程私有的全局变量。threadprivate和private的区别是private只在并行区中有效,而threadprivate属性是全局范围内有效的。
  copyin:把全局变量的值拷贝到各线程中同名的threadprivate变量中去。
C/C++ code
struct Astruct A; #pragma omp threadprivate(A)#pragma omp parallel copyin(A) do_something_to(&A); … #pragma omp parallel do_something_else_to(&A);
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#56楼 得分:0回复于:2008-08-07 15:34:22
下面我们看个程序加强理解

C/C++ code
#include <stdio.h> int main() { int i, x = 100; #pragma omp parallel for private(x) for (i=0; i<8; i++) { x += i; printf("x = %d/n", x); } printf("global x = %d/n", x); return 1; }


因为我的cpu是4核的,所以默认有4个线程,线程1跑i=0、1,线程2跑i=2、3,线程3跑i=4、5,线程2跑i=6、7,所以运行结果为:
x = 0
x = 1
x = 2
x = 5
x = 6
x = 13
x = 4
x = 9
global x = 100



下面我们把private换成firstprivate,结果就变成了
x = 100
x = 101
x = 102
x = 105
x = 106
x = 113
x = 104
x = 109
global x = 100
看出区别了吧,每个线程的x的初值都变成100了。


如果我们再加上个lastprivate:
C/C++ code
#include <stdio.h> int main() { int i, x = 100; #pragma omp parallel for firstprivate(x) lastprivate(x) for (i=0; i<8; i++) { x += i; printf("x = %d/n", x); } printf("global x = %d/n", x); return 1; }

结果如下:
x = 100
x = 101
x = 102
x = 105
x = 106
x = 113
x = 104
x = 109
global x = 113
全局的x的值最后变成了i=7的x的值,i=7是由线程4来做的。线程4在做完i=6时,私有x=106,做完i=7时,私有x=113,因为是lastprivate,113被带给全局量x了。
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#57楼 得分:0回复于:2008-08-07 15:40:52
公布一下我在48楼留得问题的答案,答案有很多种,我提供2个做参考,这2种的区别是不同的工作量划分方法:
C/C++ code
#pragma omp parallel { int i, istart, iend; int Nthrds = omp_get_num_thread(), id = omp_get_thread_num(); istart = id * N / Nthrds; iend = (id+1) * N / Nthrds; for(i=istart; i<iend; i++) { c[i] = a[i] + b[i]; } }


C/C++ code
#pragma omp parallel { int i, istart, iend; int Nthrds = omp_get_num_thread(), id = omp_get_thread_num(); for(i=id; i<iend; i+=Nthrds) { c[i] = a[i] + b[i]; } }

 
#58楼 得分:0回复于:2008-08-20 15:50:06
没测试,不过我想从利用cach的角度看

还是第一个的效率要高些

感谢楼主,继续关注
 
#59楼 得分:0回复于:2008-09-02 17:50:20
学习;谢谢楼主
 
#60楼 得分:0回复于:2008-09-03 15:53:58
跟着楼主学到了很多东西。我也一直用openmp
有一个问题一直困扰我,我采用openmp对vector进行并行运算,但发现运行时间比原来的慢了将近5倍,有时是10倍,我对openmp中可能涉及到的负载平衡进行调试,结果一样.不知道是不是openmp对vector不支持,还是程序修改有问题,请各位专家指导,小弟不尽感谢。  
另外针对vector 的操作openmp是否有更好的解决方法????????  
具体代码如下,我用的是ms+双核机器,两段程序vc2005编译都没问题。  

没有采用openmp之前的部分代码:  
QueryPerformanceCounter((LARGE_INTEGER *)&start);  
for(vector <m_class *>::iterator i=m_list.begin();i=!m_list.end();i++)  
{  
for(vector <m_class *>::iterator j=i+1;j!=m_vDefectList.end();j++)  
{  
//一系列处理  
}  
}  

QueryPerformanceCounter((LARGE_INTEGER *)&finish); //counter  
int time=finish-start;  


修改后的,用了openmp后的程序:  
vector <m_class *>::iterator i = m_list.begin();  

QueryPerformanceCounter((LARGE_INTEGER *)&start);  
#pragma omp parallel for  
for(int tempN=0; tempN <m_vDefectList.size() ; tempN++)  
{  
  for(vector <m_class *>::iterator j=i+tempN+1;j!=m_vDefectList.end();j++)  
{  
//一系列处理  
}  
}  

QueryPerformanceCounter((LARGE_INTEGER *)&finish); //counter  
int time=finish-start;  

非常感谢。  
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#61楼 得分:0回复于:2008-09-10 14:03:50
引用 60 楼 aling6888 的回复:
跟着楼主学到了很多东西。我也一直用openmp 
有一个问题一直困扰我,我采用openmp对vector进行并行运算,但发现运行时间比原来的慢了将近5倍,有时是10倍,我对openmp中可能涉及到的负载平衡进行调试,结果一样.不知道是不是openmp对vector不支持,还是程序修改有问题,请各位专家指导,小弟不尽感谢。 
另外针对vector 的操作openmp是否有更好的解决方法???????? 
具体代码如下,我用的是ms+双核机器,两段程序vc200…


貌似您的问题已经在下面贴中解决了。
http://topic.csdn.net/u/20080902/14/7efa241e-068d-4e8d-bbf9-36668829e5e0.html
 
#62楼 得分:0回复于:2008-09-22 21:48:06
顶下
 
#63楼 得分:0回复于:2008-09-23 23:21:29
支持下
 
#64楼 得分:0回复于:2008-09-24 16:57:31
专门来做记号,慢慢研究
 
#65楼 得分:0回复于:2008-09-28 15:54:17
有些内容比Intel出版的那本多核程序设计技术详细。
学习了。
还想向楼主请教一个非技术性的问题,望不吝赐教。
我是研二的学生,编程新手,等于说全部都是从头来的,包括语言。
现在刚入了个门,老板就让我来研究并行编程了。
刚刚有了点头绪,但是心里仍然没底,看了书过后不知从何下手了。
不知道有什么途径可以对内容加深理解,提高应用的能力?
当然你可能说多练习,我就是不知道给从何处开始练习啊,
不知道能不能有些例程之类,
我还要多长时间才能真正的上手呢?迷茫...
期待楼主能解惑
也希望大家多给我帮助,共同进不。
 
#66楼 得分:0回复于:2008-09-29 23:42:04
我同意 支持一下
 
  • laxila用户头像
  • laxila
  • (希腊多)
  • 等 级:
#67楼 得分:0回复于:2008-09-30 12:41:59
非常好,学习过了,谢谢楼主呀!!!
 
#68楼 得分:0回复于:2008-09-30 23:31:56
获益匪浅
 
#69楼 得分:0回复于:2008-09-30 23:37:08
要做个记号
 
#70楼 得分:0回复于:2008-10-02 18:34:02
建议大家看看 熬富江 的《并行程序设计模式》,机械工业(或者电工?),

非常不错的书
 
  • szy41用户头像
  • szy41
  • (szy41)
  • 等 级:
#71楼 得分:0回复于:2008-10-28 12:17:36
mark
 
#72楼 得分:0回复于:2008-10-28 13:09:48
mark,学习。
 
#73楼 得分:0回复于:2008-11-05 18:36:24
刚接触多核编程,前段时间搞过并行,发现差别还是相当的大啊,学习阶段……
 
#74楼 得分:0回复于:2008-12-05 12:10:07
不错, OpenMP使用上比Native API方便多了,只要在你需要并行的地方加个编译器语句指明关键的变量的属性,编译器就负责帮你创建多线程了.  
 
#75楼 得分:0回复于:2009-03-04 15:45:50
谢谢~ 辛苦了..
为什么 前边好多例子我都看不见了,只显示 CSDN图样..
为什么我再 VS2005环境中,用Intel编译器编译,会出现找不到libguide40.dll的错误提示呢??
 
  • seavon用户头像
  • seavon
  • (seavon)
  • 等 级:
#76楼 得分:0回复于:2009-03-18 12:10:56
引用 33 楼 intel_jeff 的回复:
================================================ 
OpenMP中工作量的划分与调度 
================================================ 
......
如上图所示,工作量的划分与调度有3种方式: 
1、静态:把循环的迭代按照每x次(x=chunk)迭代分为一块,这样你的总工作量就被划分成了n/x块(n为迭代次数、循环次数),然后将这些块按照轮转法依次分配给各个线程。举个例子:比如我们有100次迭代,x=chunk=4,那么我们的工作就被分为25块,假设我们有2个线程可以做工作,那么线程1分到的块是1,3,5,7....,25,线程2分到的块是2,4,6,...,24; 
2、动态:迭代分块方法同上,但是工作块被放到一个队列中,每个线程每次拿一块,做好了才能到队列里去拿下一块; 
3、Guided:这个方式是动态方式的改进。在这个方式里,分块的x是不固定的,一开始块的大小(x)比较大,随着剩余工作量的减小,块的大小也随之变小。 

关于静态的任务分配顺序好像与这里说的不是很一致,或者不同的编译器有不同的实现方式,比如在GCC上,如果任务数为N,线程数为T,
实际用到的线程数t = [N / [N/T]上取整 ]上取整,比如N=10,T=8,那么t=5,也就是只有5个线程真正启动,而线程1被分配到的是任务0和1,线程2分配到2和3,以此类推。
这样做还是有好处的,假设每个任务所需的时间一样,那么就可以在保证同样运行时间的情况下减少线程开销。
 
#77楼 得分:0回复于:2009-03-18 17:22:58
请教一个问题:

omp_get_thread_num() 这个函数,
得到的CPU编号是计算机上所有CPU的编号(全局编号),
还是当前并行区中CPU的编号(局部编号)
谢谢
 
#78楼 得分:0回复于:2009-05-05 17:30:13
期待楼主更新啊
 
  • hikaliv用户头像
  • hikaliv
  • (李博(光宇广贞))
  • 等 级:
#79楼 得分:0回复于:2009-05-15 02:06:30
标一下。谢楼主。
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#80楼 得分:0回复于:2009-05-20 10:15:03
引用 77 楼 wwwquzhinet 的回复:
请教一个问题: 

omp_get_thread_num() 这个函数, 
得到的CPU编号是计算机上所有CPU的编号(全局编号), 
还是当前并行区中CPU的编号(局部编号) 
谢谢 


这个编号是线程的编号,与CPU无关。返回的编号是0..N-1,N为总线程数
所以不管你机器上有几个CPU,假设你并行区里有8个线程,那他们返回的编号分别就是0, 1, ..., 7
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#81楼 得分:0回复于:2009-05-20 10:22:03
引用 76 楼 seavon 的回复:
引用 33 楼 intel_jeff 的回复:
================================================ 
OpenMP中工作量的划分与调度 
================================================ 
...... 
如上图所示,工作量的划分与调度有3种方式: 
1、静态:把循环的迭代按照每x次(x=chunk)迭代分为一块,这样你的总工作量就被划分成了n/x块(n为迭代次数、循环次数),然后将这些块按照轮转法依次分配给各个线程。举个例子:比如我们有…


这个是跟OpenMP实现相关了,Intel编译器的实现是尊重T的值,因为在通常情况下,T=核的数量。有核不用岂不浪费?
在你给的这个例子中,你有一个假设:每块工作量(i循环每次迭代的工作量)都是差不多的,所以8个线程与5个线程最后的运行时间都是差不多的。但是如果每块工作量不均匀的话,8个线程很可能就会比5个线程的时候快了。
 
  • intel_jeff用户头像
  • intel_jeff
  • (Jeff@英特尔 欢迎到"英特)
  • 等 级:
#82楼 得分:0回复于:2009-05-20 10:23:57
引用 75 楼 qgdbr08 的回复:
谢谢~ 辛苦了.. 
为什么 前边好多例子我都看不见了,只显示 CSDN图样.. 
为什么我再 VS2005环境中,用Intel编译器编译,会出现找不到libguide40.dll的错误提示呢??


你是说在运行的时候找不到这个DLL吧?这个DLL在Intel编译器安装目录里面,你在运行环境中把这个DLL路径加到PATH里就可以了。
 
#83楼 得分:0回复于:2009-05-26 17:20:47
辛苦了,intel_jeff大哥。。向你致敬!!!
好好学习OpenMP!!!
 
#84楼 得分:0回复于:2009-06-24 12:34:05
学习了,收获颇丰,非常感谢楼主.
 
#85楼 得分:0回复于:2009-10-08 14:31:27
学习了,非常感谢
如果能看到你是怎样用openmp解决一个复杂的算法就好了
 
#86楼 得分:0回复于:2009-12-17 14:11:53
引用 74 楼 goldencode 的回复:
不错, OpenMP使用上比Native API方便多了,只要在你需要并行的地方加个编译器语句指明关键的变量的属性,编译器就负责帮你创建多线程了.



相当经典简洁的总结啊:一是加上语句,二是指名关键变量属性。
剩下的就交给编译器来负责了~~
 
#87楼 得分:0回复于:2009-12-18 20:30:49
好贴,LZ有心人啊,先回了再细看
 
#88楼 得分:0回复于:2010-01-25 21:11:40
假设程序中有若干个线程以流水线的方式完成一个任务,想在每个线程里利用openMp
有个疑问,
如果机器是8核的话,由于线程之间协作的繁忙程度不一样,线程里的openmp设为几个并行处理比较好?
openMP在每个线程里会根据当前总体的运行情况(cpu繁忙程度)进行动态的调整并行任务个数还是会固定的采取8个核?
如果采取固定8个核会不会影响效率?
 
#89楼 得分:0回复于:2010-05-08 10:31:41
小弟在Linux下写了一个简单的omp程序,大体结构是
while(1)
{
#pragma omp parallel for
for(int i=0; i<4; i++)
{
  //数据处理
}
//显示此次循环的时间
sleep(n);
}
数据处理代码是不相关的,或者都注释掉也行,应该只是线程开销比较大。主要问题是sleep时间不同的时候,主线程CPU使用率不同,但是子线程的cpu使用率一直接近100%,使得整体的CPU使用率很高。但在windows使用相同的程序,子线程的cpu使用率基本和主线程一致。
Linux下编译的时候:g++ -fopenmp -o outfile [srcfile]
程序中包含了<omp.h>
windows下使用的是VS2008,使用的也是默认设置。
请问这是为什么啊?





 
#90楼 得分:0回复于:2010-05-10 17:04:41
请问OpenMP支持跨平台开发吗?
 
#91楼 得分:0回复于:2010-07-08 16:15:38
每天回帖即可获得10分可用分!
 
#92楼 得分:0回复于:2010-08-03 19:42:02
我用openMP写了一个程序,刚开始几秒的执行速度很快,然后速度就开始下降,这是什么原因啊?
 
#93楼 得分:0回复于:2010-08-05 21:12:22
openMP能在c++builder 6 中用么?
 
#94楼 得分:0回复于:2010-08-08 23:41:50
每天回帖即可获得10分可用分
 
#95楼 得分:0回复于:2010-09-19 23:13:25
相见恨晚啊
 
#96楼 得分:0回复于:2010-09-19 23:14:17
看不懂
 
#97楼 得分:0回复于:2010-10-02 11:16:04
您好!想请问下如何合理有效的使用多核系统中的多级缓存?谢谢
 
#98楼 得分:0回复于:2010-10-14 18:22:37
对递归算法起作用吗?
 
#99楼 得分:0回复于:2010-11-30 11:50:54
QIANG!
 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:227854次
    • 积分:3119
    • 等级:
    • 排名:第11753名
    • 原创:49篇
    • 转载:111篇
    • 译文:2篇
    • 评论:20条
    文章分类
    最新评论