已阅读5页,还剩53页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
OpenMP 入门楼主发表于:2008-05-12 16:48:04OpenMP是一个业界的标准,很早以前就有了,只是近一段时间才逐渐热起来。我们可以在C/C+和Fortran使用OpenMP、很容易的引入多线程。qOpenMP目前的标准是2.5,3.0马上也要通过了。官方网站上有你需要知道的一切信息,包括OpenMP规范文档。下图是一个典型的OpenMP程序的示意图,我们可以看到它是由串行代码和并行代码交错组成的,并行代码的区域我们把它叫做“并行区”。主线程一旦进入并行区,就自动产生出多个线程,来并行的执行。怎样在我们的代码中使用OpenMP呢?很简单,拿我们常用的C/C+代码来说,只需要插入如下pragma,然后我们选择不同的construct就可以完成不同的功能。回复次数:97 intel_jeff (Jeff英特尔 欢迎到英特) 等级: #1楼 得分:0回复于:2008-05-12 16:54:03首先,我们来看一下如何创建一个并行区:增加一行代码#pragma omp parallel,然后用花括号把你需要放在并行区内的语句括起来,并行区就创建好了。并行区里每个线程都会去执行并行区中的代码。那么怎么来控制并行区中线程的数量呢?默认情况下,并行区内线程数=系统中核的个数。如果你需要修改,方法之一是设置环境变量。下一节我们将看一个最简单的OpenMP代码,看看并行区是怎样工作的(待续。) intel_jeff (Jeff英特尔 欢迎到英特) 等级: #3楼 得分:0回复于:2008-05-13 11:16:47我们来看一个最简单的OpenMP程序例子:=#include int main() #pragma omp parallel int i; printf(Hello Worldn); for(i=0;iicl /nologo HelloWorlds.cHelloWorlds.cHelloWorlds.c(4): warning #161: unrecognized #pragma #pragma omp parallel 串行代码执行的结果如下:D:testHelloWorlds.exeHello WorldIter:0Iter:1Iter:2Iter:3Iter:4Iter:5GoodBye World下面我们加上 /Qopenmp 开关重新编译,我们会看到编译器给出提示说已经把并行区给做并行化了。D:testicl /nologo /Qopenmp HelloWorlds.cHelloWorlds.cHelloWorlds.c(4): (col. 5) remark: OpenMP DEFINED REGION WAS PARALLELIZED.我的机器是4核,运行这个程序就打印出如下结果。我们可以看到每次运行打印出来的东西顺序是不一定的,这个符合多线程程序的特性。在4核的机器上,并行区内就产生了4个线程同时执行for循环打印,默认线程数=核的个数。D:testHelloWorlds.exeHello WorldIter:0Iter:1Iter:2Iter:3Iter:4Iter:5Hello WorldIter:0Hello WorldIter:0Iter:1Iter:2Iter:3Iter:4Iter:5Hello WorldIter:0Iter:1Iter:1Iter:2Iter:2Iter:3Iter:3Iter:4Iter:4Iter:5Iter:5GoodBye World我们来修改一下线程的数量,然后再运行一下代码,看下运行结果D:testset OMP_NUM_THREADS=2D:testHelloWorlds.exeHello WorldIter:0Iter:1Iter:2Iter:3Iter:4Iter:5Hello WorldIter:0Iter:1Iter:2Iter:3Iter:4Iter:5GoodBye WorldD:test现在我们对并行区有了一定的了解,并行区里每个线程执行的代码是一样的,做的事情似乎也是一样的,但是实际工作中,我们希望把一部分工作分配给不同线程来做,这应该怎么实现呢?请看下节。(待续。) 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合并未一行,这样好多了,是吧。(待续。) youxia000 (无剑无我) 等级: #7楼 得分:0回复于:2008-05-14 19:20:10能问个问题么多线程对可分的计算是很好的但是对大量内存的访问是不是也能提速呢,比如我做图像处理,做一个gauss光滑,要访问周围点然后来计算,并且前后不相关,可以分多线程,计算方面肯定提速了但是对不同线程的内存访问是不是也分别用各自的缓存似乎这个问题和多核的cpu是共享缓存,还是各自独立缓存有关, intel_jeff (Jeff英特尔 欢迎到英特) 等级: #9楼 得分:0回复于:2008-05-16 11:24:53能问个问题么 多线程对可分的计算是很好的 但是对大量内存的访问是不是也能提速呢, 比如我做图像处理,做一个gauss光滑,要访问周围点然后来计算,并且前后不相关,可以分多线程,计算方面肯定提速了 但是对不同线程的内存访问是不是也分别用各自的缓存 似乎这个问题和多核的cpu是共享缓存,还是各自独立缓存有关,最好能利用好缓存,尽量把相近的点一起做。你可以尝试不同的划分方法,比如把大图切割成 n x n 的小块,每个线程做一个小块;或者每个线程做1行,即线程1做第1,n+1,2n+1行,第2个线程做第2,n+2,2n+2行,n为线程数。多试试几个方法,应该有一个最适合你的方法。 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进行保护。待续。) Kaile (领头羊) 等级: #12楼 得分:0回复于:2008-05-28 13:19:58我是OPENMP新手,对于上一段代码,我还是有困惑:设置了critical以后,sum+= . 这句话说明多个线程不同时作加法,但是还是每个线程做N次加法,这样N线程数的结果与单线程的N次结果会大相径庭,对吗?有什么办法既提高速度又不改变逻辑了? Kaile (领头羊) 等级: #13楼 得分:0回复于:2008-05-28 14:43:45我上面的理解不对,#pragma omp parallel for 这句话应该是把for循环分为N部分,分配给每个独立的线程。因为sum+= N这一句话牵涉到读sum,所以不能设置为shared.我这样理解对吗? Kaile (领头羊) 等级: #14楼 得分:0回复于:2008-05-28 21:20:47上面的代码如果这样改: #pragma omp for reduction(+: sum) for(int i = 0; i N; i+)sum += ai + bi;是不是和范例的代码等价了? 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 (领头羊) 等级: #17楼 得分:0回复于:2008-05-29 15:42:48#pragma omp parallel forfor (i=0;iMAX;i+) for (j=0;jMAX;j+) tij=FALSE;还有,象上面这个语句,i 是私有的, j 是shared,运行起来会不会有问题了? intel_iclifort (iclifort) 等级: #18楼 得分:0回复于:2008-05-29 15:56:13引用 17 楼 Kaile 的回复:#pragma omp parallel forfor (i=0;i MAX;i+) for (j=0;j MAX;j+) tij=FALSE;还有,象上面这个语句,i 是私有的, j 是shared,运行起来会不会有问题了?并行区(Parallel Region)内, 未经声明, 所有的变量都是共享的, 只有一个例外 intel_iclifort (iclifort) 等级: #19楼 得分:0回复于:2008-05-29 16:03:09引用 16 楼 Kaile 的回复:谢谢及时回复。那么14楼的分析有没有问题了?问题在哪里?没有问题, 这是OpenMP提供的累加归约(Reduction)操作. 另外, 还可以支持乘, 逻辑运算等归约操作 intel_iclifort (iclifort) 等级: #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 probabilitythat 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 cacheresources 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)这篇白白书中有详细的说明: /technology/architecture/sma.pdf 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 总的sum,这个总的sum值将被带出并行区并赋给全局的那个sum变量,因此,当这个并行区的代码执行完以后,我们的sum变量的值就是我们期望得到的值了。是不是比前面用临界区的方法要好得多、代码也会快得多呢?下图是归约支持的操作符:好了,来给大家做个小作业。下面代码是一个串行的求Pi的代码,使用的是积分的办法。请大家把这个代码用OpenMP来做并行化。 Kaile (领头羊) 等级: #23楼 得分:0回复于:2008-05-29 21:12:34我来试试:#include 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 = %fn),pi); Kaile (领头羊) 等级: #24楼 得分:0回复于:2008-06-02 15:50:57#pragma omp parallel for for(int i = 0; i 4)break;在学习OpenMP中,发现这样的break语句不能在这里用,如果循环中有这种逻辑,如何处理? Kaile (领头羊) 等级: #25楼 得分:0回复于:2008-06-02 15:54:03我在单核心的机器上测试,如果加上#pragma omp parallel sections或者:#pragma omp parallel for reduction(+:sum)二种语句,性能会急剧下降。如果只加 #pragma omp parallel for性能不变化。请问这种情况是正常的吗? intel_iclifort (iclifort) 等级: #26楼 得分:0回复于:2008-06-02 16:29:21引用 25 楼 Kaile 的回复:我在单核心的机器上测试,如果加上#pragma omp parallel sections或者:#pragma omp parallel for reduction(+:sum)二种语句,性能会急剧下降。如果只加 #pragma omp parallel for性能不变化。请问这种情况是正常的吗?请先考虑正确性, 再考虑性能 对我有用0 丢个板砖0 引用 举报 管理 TOP Kaile (领头羊) 等级: #27楼 得分:0回复于:2008-06-02 16:32:03当然是原来的逻辑没有改变了。 对我有用0 丢个板砖0 引用 举报 管理 TOP intel_jeff (Jeff英特尔 欢迎到英特) 等级: #28楼 得分:0回复于:2008-06-04 11:09:31引用 24 楼 Kaile 的回复:#pragma omp parallel for for(int i = 0; i 4) break; 在学习OpenMP中,发现这样的break语句不能在这里用,如果循环中有这种逻辑,如何处理? 这样的循环是不能并行的,你需要改写你的代码(如果可能的话),至于怎么改写就要看具体情况了。 对我有用1 丢个板砖0 引用 举报 管理 TOP 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原理时说的)。在程序逻辑相同的情况下,应该不会大幅度降低性能。你的测试代码能否贴出来看看? 对我有用0 丢个板砖0 引用 举报 管理 TOP 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)return m_nValue;int v1 = 0,v2=0 ;#pragma omp parallel sections #pragma omp sectionv1 += 10;#pragma omp sectionv2 += 20;m_nValue += v1 + v2;qs(count);return m_nValue;很简单的测试,对话框上一个按钮,按一下进入循环体,执行一个递归函数。openmp 的section段也很简单,最后输出执行时间,但使用不使用OPENMP的结果让人大跌眼镜:Value is 4800000, Tick count is 3828 /使用openmp sectionsValue is 4800000, Tick count is 16 / 不使用看来逻辑没问题,就是性能下降太厉害。请教大侠这种情况如何是好? 对我有用0 丢个板砖0 引用 举报 管理 TOP Kaile (领头羊) 等级: #31楼 得分:0回复于:2008-06-13 10:43:16感觉是不是粒度分得太细,线程的开销已经大于多线程并行带来的好处,加上多重循环的累积,造成性能下降厉害。有没有办法初始化线程,以后不动态创建和析构,这样是不是减少损耗? 对我有用0 丢个板砖0 引用 举报 管理 TOP intel_jeff (Jeff英特尔 欢迎到英特) 等级: #32楼 得分:0回复于:2008-06-16 14:22:47同意Kaile的看法,粒度太细了,应该尽可能在外层的循环用omp parallel for来做多线程化 对我有用0 丢个板砖0 引用 举报 管理 TOP 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 对我有用0 丢个板砖0 引用 举报 管理 TOP Kaile (领头羊) 等级: #34楼 得分:0回复于:2008-06-29 21:28:50还没有新内容吗?更新能否快一些。 对我有用0 丢个板砖0 引用 举报 管理 TOP intel_jeff (Jeff英特尔 欢迎到英特) 等级: #35楼 得分:0回复于:2008-07-02 13:34:49好的,前些时间有些忙,希望今天能更新,谢谢 _ 对我有用0 丢个板砖0 引用 举报 管理 TOP 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(); (待续) 对我有用0 丢个板砖0 引用 举报 管理 TOP 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; in; i+) ai = bigFunc1(i);#pragma omp for schedule(dynamic,1) for(int j=0; jm; j+) bj = bigFunc2(j); 对我有用0 丢个板砖0 引用 举报 管理 TOP Kaile (领头羊) 等级: #38楼 得分:0回复于:2008-07-03 08:25:50我看别的资料没有你解释得这么详细的,no wait我一直不知道怎么用,现在明白了。 对我有用0 丢个板砖0 引用 举报 管理 TOP n_yHHy_n (n_yHHy_n) 等级: #39楼 得分:0回复于:2008-07-04 12:40:25学习 对我有用0 丢个板砖0 引用 举报 管理 TOP gubin04110245 等级: #40楼 得分:0回复于:2008-07-04 13:32:14路过,顶 对我有用0 丢个板砖0 引用 举报 管理 TOP xiao7cn (FriedChicken) 等级: #41楼 得分:0回复于:2008-07-04 17:39:08眼泪哗哗的 对我有用0 丢个板砖0 引用 举报 管理 TOP wangyj705 等级: #42楼 得分:0回复于:2008-07-05 10:15:39榜样啊。学习中。顶。 对我有用0 丢个板砖0 引用 举报 管理 TOP ewqtan (学习) 等级: #43楼 得分:0回复于:2008-07-05 11:05:35顶 对我有用0 丢个板砖0 引用 举报 管理 TOP e_bot (挖坟工Never Mind t) 等级: #44楼 得分:0回复于:2008-07-07 19:27:14打酱油路过看看 对我有用0 丢个板砖0 引用 举报 管理 TOP next163 (毛爪) 等级: #45楼 得分:0回复于:2008-07-08 17:19:52谢谢 对我有用0 丢个板砖0 引用 举报 管理 TOP sz000000001 (程序员在深圳) 等级: #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 m
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 线绕电阻器、电位器制造工岗前岗中实操考核试卷含答案
- 农产品品相管理员操作安全评优考核试卷含答案
- 北京市建筑施工作业人员安全生产知识教育培训考核试卷及答案
- 桥梁基础测量放线施工工艺
- 2026年设备检维修考试题及答案
- 双层笼体整体同心度校正方法
- 园林绿化立体花坛养护管理指南
- 施工现场安全计划
- 2026 湖北省巫溪县建筑特殊工种架子工证考试参考题库-含答案
- 2026年高考历史时间轴记忆技巧及模拟试卷
- 《铪及铪合金高低倍组织检验方法》
- 大学生劳动教育第五章崇尚劳动实践
- 输电线路数字化安全管理
- 《神雕侠侣》江湖与爱情的绝美传说
- 感冒清热颗粒工艺规程
- 2023年临沧市市级单位遴选(选调)考试题库及答案
- 茶文化与茶艺PPT全套完整教学课件
- 生物技术制药-课件
- 合肥市社区工作者考试真题及答案2022
- 贵州某矿尾矿库岩土工程勘察
- 斗式提升机技术规范书
评论
0/150
提交评论