西西河

主题:【求助】:请教信息技术方面的大牛有关多线程的问题 -- newtime

共:💬51 🌺45
分页树展主题 · 全看首页 上页
/ 4
下页 末页
                • 家园 本质是一样的

                  都是利用更快更贵的存储器来存放本来存不下的数据,只不过技术让整个缓存架构变多了。

                  intel CPU里面的超线程hyperthreading,其实是让一组计算单元被多组context registers使用,所以在两个thread没有共同的硬件资源的时候,是可以提高执行速度的;但是如果两个thread竞争同一个计算资源,那么就要等待,同时还增加了context switch的时间,必然是更慢的。

                  另外鸡蛋里面挑根骨头

                  计算机体系架构和编译器优化效果的关键,就在对读写内存的指令数的处理上。

                  老叫花看来,这个优化的基本原则,是找瓶颈,用最少的努力去获得最大的收益。编译优化最早是优化循环这个大瓶颈,循环弄的差不多了,访存就变成最大的瓶颈了。访存也有很多种优化方法,比如你说的对指令数的优化,或者更有效一点的:prefectch.

                  另:谢宝

                  恭喜:你意外获得【通宝】一枚

                  鲜花已经成功送出。

                  此次送花为【有效送花赞扬,涨乐善、声望】

                  • 家园 真正的专家出手了,我这只是皮毛而已,抛砖引玉

                    当年学的也比较肤浅,这两年的职业发展也没沿着这个专业走下去。

                    解释一下,其实循环展开的主要目的,也是为了找到更多无依赖关系的指令,填充到访存质量等需多周期完成指令的gap,另外就是分支预测,我还是认为优化的核心问题是出在访存上。

                    缓存预取指令要用好,先要有合理的数据结构和算法。

                    • 家园 客气了

                      你说的没错,访存的确是最费时间的指令,我记得连开方这种指令都足够快了,但是CPU永远比内存快太多。所以这个就是优化的重点。

                      优化的目标是增加并行度,instruction reordering,乱序执行,SSE这些东西,都是用软硬件的方法增加ILP。不过现在因为mobile computing热起来了,大家要让CPU凉下去,所以能耗成为优化里面的新因素,bit per watt要高,好多硬件的trick就不能用了,我记得intel atom里面就是放弃了大多数的乱序执行来节约能量,只在特定指令序列才进行乱序执行。

                      当年我做的一个simulation里面,如果用局部的乱序执行,可以以10%不到的性能损失,换回30%左右的能耗降低。

              • 家园 两种处理方法

                对于超大规模稀疏矩阵的并行计算,可以只存储非零元素,用链表或者哈希结构压缩存储。缺点是会增加每次有效操作的读取次数,但对于超大规模稀疏矩阵,绝大部分元素都是0,这种情况下,用链表遍历的读取次数要远小于数组遍历。

                另一方面,缓存与内存存在特殊的映射关系,缓存中的内容对应内存的某个区域,只要你的读取操作都集中在这个区域内,缓存更新频率低,影响也很小,忌讳的是在读取过程中坐标乱跳,这样缓存需要经常更新。你在编程过程中,可以将数组遍历过程与缓存大小相结合,采用中间变量和特殊算法,提高效率。

                当年缓存只有64K的时代,内存才几兆的时代,这种小技法是很多的,只是现在动辄8M缓存,几十G内存,大家反而少用了这些优化技术了。

    • 家园 极大可能是共享变量访问的问题

      如果你的这个程序是C++的,把ramdon_number去掉以后应该没有任何问题,多线程在多核CPU上肯定快。但对Fortran程序,按我对这个语言的粗浅理解,Thread_Proc0的所有局部变量在两个线程都是共享的(同时说明:你的运算可能因此无法获得你预期的结果)。如果是并行版的编译器,那么访问这些变量的所有操作都要自动加锁,如此的话多线程程序将显著慢于单线程程序。

      一个测试方法是把Thread_Proc0复制一份并改名Thread_Proc1,然后两个线程分别调用两个运算函数。如果这个方式下效率显著提高,则说明是Fortran语言的问题。否则要另找原因。

    • 家园 多线程是否提高效率,取决于你的应用

      如果你想用多线程来提高效率,那么就是提高CPU Utilization。如果你有两种task,一种是CPU Intensive,一种是IO intensive,那么用multithreading就可以极大地提高效率,因为在IO Intensive的task等待的时候,系统就可以执行CPU Intensive的task。

      你现在两个thread都是CPU Intensive的,如果用单核处理器就没有必要用多线程,因为thread之间context switch的开销完全没有必要了。

      如果用多核处理器,很可能操作系统是不是把这两个thread分配到一个CPU上去了(你的操作系统应该不仅仅有这两个thread在运行)。这东西你没法精确控制,只能托付给底层操作系统。当然,这验证了Vista果然弱智。

      试试看用Java重写你的程序,看看JVM会不会聪明一点。

    • 家园 多线程的问题

      当年pentium4的多线程对科学计算的影响就是负的,现在i7估计还是这样。我们一般都用mpi或pvm,一般科学计算不用thread,可以bios里把多线程关了看看结果。我知道以前志强等做cluster时都是在bios里把多线程关了。

    • 家园 目前并行计算一般采用MPI而不是openMP

      看看运算过程中你的各个CPU的负载情况,是两个核在跑还是一个核在跑。

      • 家园 谢谢!

        是两个核在跑。

        两线程的cpu使用大约是单线程的两倍多。但是两线程所需要的时间却比单线程长得多。很不明白为什么。

        关键词(Tags): #多线程
        • 家园 你改一下程序试试

          先用random_number(x)生成两个随机数组,然后用数组里的元素进行计算,而不是在线程循环里调用随机数生成器。看看效果如何。

          另外,编译的时候用的优化等级是O2还是O3?

          • 家园 修改

            去掉了random_number, 多线程改善了一些,但还是比单线程要慢。

            编译的时候用的优化等级是o3

            • 修改
              家园 去掉了random_numbe啥意思

              把子程序改成简单累加程序,看看基本效果?

              我没在windows下编过并行计算程序。

              • 家园 是的

                我把子程序改成了累加程序

                • 是的
                  家园 在子程序里加一个读取CPU的ID的函数

                  如果有变化就打印出来,我怀疑线程没有和CPU绑定,在来回跳,曾经听说过类似情况。

                  另外,多线程程序对于计算密集型且规模较大的不适用,应采用多进程程序。

分页树展主题 · 全看首页 上页
/ 4
下页 末页


有趣有益,互惠互利;开阔视野,博采众长。
虚拟的网络,真实的人。天南地北客,相逢皆朋友

Copyright © cchere 西西河