openMP是在cpu 上的线程并行,cuda 是在gpu 上的线程并行,有没有人做过这方面的比较,哪种效率更有优势,异或是两者结合能否超越单纯使用一种?
LZ您好:
这两个基本不能直接相比较的,OPENMP仅能用于CPU,CUDA仅能用于GPU(不考虑非官方的一些支持)。这是两种差异巨大的硬件体系下的比较,难以给出直接的结论,也无法论及哪种更有效率。
比如您可以比较CUDA和OPENCL哪种更有效率,或者CUDA 和OPENACC哪种更有效率或者更具灵活性,这两个比较起码可以在同样的硬件平台上进行。而OPENMP实现了多少CPU效率,CUDA实现了多少GPU效率,这两个效率根本没有可比性的。
以及,两者结合使用,一般也仅指实现多host端线程执行CUDA时,多个host端的线程使用OPENMP创建;或者在GPU运行时,CPU端使用OPENMP实现多线程干一些辅助的工作等。
综上,这两者不具备直接的可比性。
个人观点,供LZ参考。
祝您好运~
恩,有道理。
但如果我考虑普遍的情况,比如 CPU 一般的机器就双核或四核,而大多数机器的显卡配置都属于中端产品,普遍计算能力在2.0以上,所以,在这种普遍情况下,是不是cuda 更有优势呢
LZ您好:
这里有一个重要的概念需要澄清:CUDA的计算能力版本(如2.0,2.1,3.0,3.5之类),指的是可支持的特性,而不是指计算峰值的大小。
因而您文中的比较(CPU的性能 VS GPU的特性)就显得没有意义了。
以及CPU和GPU他们分别有不同的特点和用途,不是互相代替关系。
大致如此,祝您编码顺利~
哦 原来如此,感谢指导:)
不客气的,欢迎您常来论坛。
祝您编码顺利~
基本上把openMP的#pragma omp parallel for 迴圈拆掉,適度的重新撰寫程式碼CUDA都可以比openMP快很多,不過能快多少則是仰賴程式撰寫者的功力,
很多文章比較GPU跟CPU的加速比,CPU端大多數都是已經用openMP的時間為基準下去比的
您好:
1:重新撰写为CUDA之后是在GPU上运行的,所以这个比较变成了OPENMP在某特定CPU平台下的效能 VS CUDA在某特定GPU平台下的效能。这就变成了不同硬件平台的计算速度对比,而不再单纯是两种方法的对比。CUDA如果跑在很渣的GPU上一样也快不了。
此外编程者的水平确实会影响最后的结果,无论CPU平台还是GPU平台均是如此。
2:为了公平起见,CPU也需要用OPENMP甚至其他进一步的方法优化以发挥其效能的。所以您说的是正确的做法。
这样混合使用openmp 和 cuda行不行?有没有起到实质性的作用。cpu是4核的。
#pragma omp parallel for
for(int i = 0 ; i <100; i++)
{
malloc()
cudamalloc()
cudamemcpy()
kernel<<<>>>
cudamemcpy()
}
运行的时候没跑完,程序崩了,所以没法统计时间。
LZ您好:
您的意图是?
1:如果您是多GPU系统,然后打算每个host端线程控制一个GPU,那么您这么写是不行的,因为您这里没有设定对应的device,这些操作都在默认的device上。
2:如果您是单GPU系统,打算多个host端线程分时使用GPU,并进行一定的传输和计算掩盖。那么您还需要做一定的改动,您需要建立多个stream,每个host端线程使用不同的stream,并使用异步版本的cudaMemcpy等。
3:以及注意到您是将一个100次的循环直接OPENMP展开的,您是随手这么写的么?您多线程发布GPU工作,需要仔细安排一下这个被展开的循环。
您可以参考一下 CUDA 5 Samples里面的cudaOpenMP和simpleMultiGPU这两个例子的写法。
大致如此,供您参考。
祝您编码顺利~
1.本程序是处理很多张影像,每个循环处理一张。我的意图是用openMP 展开循环,每个循环里去调用kernel。
2.程序是按照单gpu编写的。
3.100次数随手写的,实际中往往大于100. 您说的“多线程发布GPU工作,需要仔细安排一下这个被展开的循环。”不大理解,具体是指的什么
4.sample刚看了, 是多GPU情况下使用openMP,和单GPU使用不大一样
谢谢!
LZ您好:
根据您新补充的信息,大致推断您为多核CPU+单GPU系统。
以及推测您的9#的“实质作用”指的是计算和传输互相掩盖。
那么这大致是10#中2:所叙述的内容。
按照您之前的写法是不可以的,因为您所有的GPU工作都发布在默认CPU的默认stream上,他们将串行执行,在时间上和您一个host端线程直接循环发布是一样的效率。
如果您要实现计算和传输互相掩盖,那么必须使用多个stream以及异步版本的cudaMemcpy以及host端的页锁定内存。此时无论主机端一个线程以不同stream的方式向GPU发布多个任务流,还是主机端建立多个线程,每个线程维护一个stream,以求得更大的灵活性,都是可以的。
以及建立主机端的多个线程的时候,您可以考虑OPENMP。
由上可知,您建立的主机端的线程数量其实是和您需要创建的stream的数量挂钩的,这个并不取决于您的CPU的核心数量,但是您的CPU有多个物理核心的话,会快一些。
以及您依然可以适当参考之前的simpleMultiGPU的例子,参考里面多steam,异步copy和页锁定内存的用法。只是之前的cudaSetDevice()你这里不再需要。以及您需要将单主机线程循环发放GPU指令的部分改写为OPENMP的多主机端线程方式。
至于您的100次循环,这个大致上是直接来源于您之前的代码。以及您没有指明OMP使用了多少个host端线程展开。如前所述所需的host端线程数量只和您的stream数量有关。以及,假定您需要n个主机端线程,直接对一个大于n的循环用OMP展开,那么内部是如何实现的,我并不清楚,也无实测过能否很好地向GPU发送任务,以及详细讨论此OMP行为也超出了本版的范围。所以我不确定您直接这样使用(在指定了stream等条件下,并非您初始写法),能否达到好的效果。
以及,您至少可以写一个和stream数量相等的小循环,并使用OPENMP展开;然后外面加一个循环来反复启动这个小循环以每次加载不同的工作任务。这样或许更好。不过对OMP的讨论超出本版范围,我也没有相关的经验,也无评估过这样做的开销情况,并不保证这是最好的做法。
大致如上,供您参考,欢迎其他网友/斑竹/NV支持加以补充和讨论。
祝您编码顺利~
感谢这么细心讲解,我也是刚接触openMP,很多都不太懂。
用stream实现后 我发现性能并没有提升,因为程序瓶颈主要在于cpu 读影像,大概占用了60%-70%的时间,所以我觉得用stream 可能作用并不太大。
LZ您好:
根据您13#的信息,您说您的主要瓶颈在于CPU读取影像,那么这个环节和GPU无关了。
我们只能讨论GPU自身处理以及GPU和host端内存传输数据。以及使用多stream多少可以在这两个环节中实现计算和传输相互掩盖的。
大致如此,祝您编码顺利~