jjzjj

c++ - 英特尔 C++ 编译器 ICC 似乎忽略了 SSE/AVX 设置

coder 2024-02-25 原文

我最近下载并安装了适用于 Linux 的英特尔 C++ 编译器 Composer XE 2013,可免费用于非商业开发。 http://software.intel.com/en-us/non-commercial-software-development

我在 Ivy 桥系统(具有 AVX)上运行。我有两个版本的函数做同样的事情。一个不使用 SSE/AVX。另一个版本使用 AVX。在 GCC 中,AVX 代码比标量代码快大约四倍。但是,使用 Intel C++ 编译器时性能要差得多。使用 GCC 我这样编译

gcc m6.cpp -o m6_gcc -O3 -mavx -fopenmp -Wall -pedantic

使用 Intel 我这样编译

icc m6.cpp -o m6_gcc -O3 -mavx -fopenmp -Wall -pedantic

此时我只使用 OpenMP 进行计时(使用 omp_get_wtime())。 奇怪的是,如果我将 avx 选项更改为 msse2,则代码无法使用 GCC 进行编译,但可以使用 ICC 进行编译。事实上,我可以将 mavx 放在一起,它仍然可以编译。似乎无论我尝试什么选项,它都会编译但不会优化使用 AVX 代码。所以我想知道我在使用 ICC 启用/禁用 SSE/AVX 时是否做错了什么?

这是我正在使用的 AVX 函数。

inline void prod_block4_unroll2_AVX(double *x, double *M, double *y, double *result) {
    __m256d sum4_1 = _mm256_set1_pd(0.0f);
    __m256d sum4_2 = _mm256_set1_pd(0.0f);

    __m256d yrow[6];
    for(int i=0; i<6; i++) {
        yrow[i] = _mm256_load_pd(&y[4*i]);
    }
    for(int i=0; i<6; i++) {
        __m256d x4 = _mm256_load_pd(&x[4*i]);
        for(int j=0; j<6; j+=2) {
            __m256d brod1 = _mm256_set1_pd(M[i*6 + j]);
            sum4_1 = _mm256_add_pd(sum4_1, _mm256_mul_pd(_mm256_mul_pd(x4, brod1), yrow[j]));
            __m256d brod2 = _mm256_set1_pd(M[i*6 + j+1]);
            sum4_2 = _mm256_add_pd(sum4_2, _mm256_mul_pd(_mm256_mul_pd(x4, brod2), yrow[j+1]));
        }
    }
    sum4_1 = _mm256_add_pd(sum4_1, sum4_2);
    _mm256_store_pd(result, sum4_1);
}

这里是以秒为单位的计时信息。我运行了对应于 L1、L2 和 L3 缓存范围的三个范围。我在 L1 区域只得到 4x。请注意,ICC 具有更快的标量代码但更慢的 AVX 代码。

GCC:
nvec 2000, repeat 100000
time scalar 5.847293
time SIMD 1.463820
time scalar/SIMD 3.994543

nvec 32000, repeat 10000
time scalar 9.529597
time SIMD 2.616296
time scalar/SIMD 3.642400
difference 0.000000

nvec 5000000, repeat 100
time scalar 15.105612
time SIMD 4.530891
time scalar/SIMD 3.333917
difference -0.000000

ICC:
nvec 2000, repeat 100000
time scalar 3.715568
time SIMD 2.025883
time scalar/SIMD 1.834049

nvec 32000, repeat 10000
time scalar 6.128615
time SIMD 3.509130
time scalar/SIMD 1.746477

nvec 5000000, repeat 100
time scalar 9.844096
time SIMD 5.782332
time scalar/SIMD 1.702444

最佳答案

两点:

(1) 看来您在代码中使用了 intel intrinsic —— g++ 和 icpc 不一定实现相同的 intrinsics(但它们中的大部分重叠)。检查需要导入的头文件(g++ 可能需要提示来为您定义非艺术性)。 g++ 失败时会给出错误信息吗?

(2) 编译器标志 do 并不意味着将生成指令(来自 icpc --help): -msse3 可能生成 Intel(R) SSE3、SSE2 和 SSE 指令

这些标志通常只是对编译器的提示。您可能需要查看 -xHost 和 -fast。

It seems no matter what options I try it compiles but does not make optimal use of the AVX code.

你是如何检查这个的?如果存在其他瓶颈(例如内存带宽),您可能看不到 4 倍的加速。

编辑(基于问题编辑):

看起来 icc 标量比 gcc 标量更快——可能是 icc 对标量代码进行了矢量化。如果是这种情况,我不会期望在手动编码矢量化时 icc 有 4 倍的加速。

至于 icc 在 5.782332s 和 gcc 在 3.509130s 之间的区别(对于 nvec 5000000);这是出乎意料的。根据我掌握的信息,我无法判断为什么两个编译器之间的运行时存在差异。我建议查看两个编译器发出的代码 ( http://www.delorie.com/djgpp/v2faq/faq8_20.html )。此外,请确保您的测量结果是可重现的(例如,多路计算机上的内存布局、热/冷缓存、后台进程等)。

关于c++ - 英特尔 C++ 编译器 ICC 似乎忽略了 SSE/AVX 设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17031192/

有关c++ - 英特尔 C++ 编译器 ICC 似乎忽略了 SSE/AVX 设置的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby - Sinatra set cache_control to static files in public folder编译错误 - 2

    我不知道为什么,但是当我设置这个设置时它无法编译设置:static_cache_control,[:public,:max_age=>300]这是我得到的syntaxerror,unexpectedtASSOC,expecting']'(SyntaxError)set:static_cache_control,[:public,:max_age=>300]^我只想将“过期”header设置为css、javaascript和图像文件。谢谢。 最佳答案 我猜您使用的是Ruby1.8.7。Sinatra文档中显示的语法似乎是在Ruby1.

  3. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  4. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  5. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  6. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  7. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

  8. .net - 是否有 Ruby .NET 编译器? - 2

    是否有适用于Ruby语言的.NETFramework编译器?我听说过DLR(动态语言运行时),这是否将使Ruby能够用于.NET开发? 最佳答案 IronRuby是Microsoft支持的项目,建立在动态语言运行时之上。 关于.net-是否有Ruby.NET编译器?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/199638/

  9. ruby - Sinatra + Heroku + Datamapper 使用 dm-sqlite-adapter 部署问题 - 2

    出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t

  10. ruby - Ruby 中字符串运算符 + 和 << 的区别 - 2

    我是Ruby和这个网站的新手。下面两个函数是不同的,一个在函数外修改变量,一个不修改。defm1(x)x我想确保我理解正确-当调用m1时,对str的引用被复制并传递给将其视为x的函数。运算符当调用m2时,对str的引用被复制并传递给将其视为x的函数。运算符+创建一个新字符串,赋值x=x+"4"只是将x重定向到新字符串,而原始str变量保持不变。对吧?谢谢 最佳答案 String#+::str+other_str→new_strConcatenation—ReturnsanewStringcontainingother_strconc

随机推荐