- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
过去几天我一直在阅读有关 gcc 4.7 的自动向量化。我按照我在网上看到的一些示例进行操作,设置似乎是正确的。但是当我实际运行代码并比较打开或关闭矢量化时,运行时间没有明显差异。
这是我一直在使用的代码:
#include <string.h>
#include <stdlib.h>
#include <emmintrin.h>
#include <stdio.h>
#include <math.h>
int main(int argc, char** argv) {
long b = strtol(argv[2], NULL, 0);
unsigned long long int i;
unsigned long long int n = (int)pow(2,29);
float total = 0;
float *__restrict__ x1;
float *__restrict__ y1;
posix_memalign((void *)&x1, 16, sizeof(float)*n);
posix_memalign((void *)&y1, 16, sizeof(float)*n);
float *__restrict__ x = __builtin_assume_aligned(x1,16);
float *__restrict__ y = __builtin_assume_aligned(y1,16);
for (i=0;i<n;i++) {
x[i] = i;
y[i] = i;
}
for (i=0; i<n; i++) {
y[i] += x[i];
}
printf("y[%li]: \t\t\t\t%f\n", b,y[b]);
printf("correct answer: \t\t\t%f\n", (b)*2);
return 0;
}
其中一些内容对我来说似乎是多余的,但对于让编译器了解正在发生的事情(尤其是数据对齐的事实)来说是必要的。从命令行读取的“b”变量就在那里,因为我对编译器完全优化循环感到疑惑。
这是启用矢量化时的编译器命令:
gcc47 -ftree-vectorizer-verbose=3 -msse2 -lm -O2 -finline-functions -funswitch-loops -fpredictive-commoning -fgcse-after-reload -fipa-cp-clone test.c -ftree-vectorize -o v
基本上,这等同于只使用 -O3。我把标志放在自己身上,这样我需要做的就是删除“ftree-vectorize”并能够测试没有矢量化的结果。
这是 ftree-vectorize-verbose 标志的输出,表明代码实际上正在被矢量化:
Analyzing loop at test.c:29
29: vect_model_load_cost: aligned.
29: vect_model_load_cost: inside_cost = 1, outside_cost = 0 .
29: vect_model_load_cost: aligned.
29: vect_model_load_cost: inside_cost = 1, outside_cost = 0 .
29: vect_model_simple_cost: inside_cost = 1, outside_cost = 0 .
29: vect_model_store_cost: aligned.
29: vect_model_store_cost: inside_cost = 1, outside_cost = 0 .
29: cost model: Adding cost of checks for loop versioning aliasing.
29: Cost model analysis:
Vector inside of loop cost: 4
Vector outside of loop cost: 4
Scalar iteration cost: 4
Scalar outside cost: 1
prologue iterations: 0
epilogue iterations: 0
Calculated minimum iters for profitability: 2
29: Profitability threshold = 3
Vectorizing loop at test.c:29
29: Profitability threshold is 3 loop iterations.
29: created 1 versioning for alias checks.
29: LOOP VECTORIZED.
Analyzing loop at test.c:24
24: vect_model_induction_cost: inside_cost = 2, outside_cost = 2 .
24: vect_model_simple_cost: inside_cost = 2, outside_cost = 0 .
24: not vectorized: relevant stmt not supported: D.5806_18 = (float) D.5823_58;
test.c:7: note: vectorized 1 loops in function.
请注意,向量化在 3 次迭代后是有利可图的,我正在运行 2^29~=500,000,000 次迭代。所以我应该期待一个截然不同的运行时并关闭矢量化,对吧?
好吧,这是代码的运行时间(我连续运行了 20 次):
59.082s
79.385s
57.557s
57.264s
53.588s
54.300s
53.645s
69.044s
57.238s
59.366s
56.314s
55.224s
57.308s
57.682s
56.083s
369.590s
59.963s
55.683s
54.979s
62.309s
扔掉那个奇怪的 ~370 秒异常值,平均运行时间为 58.7 秒,标准差为 6.0 秒。
接下来,我将使用与之前相同的命令进行编译,但不使用 -ftree-vectorize 标志:
gcc47 -ftree-vectorizer-verbose=3 -msse2 -lm -O2 -finline-functions -funswitch-loops -fpredictive-commoning -fgcse-after-reload -fipa-cp-clone test.c -o nov
再次连续运行该程序 20 次会产生以下次数:
69.471s
57.134s
56.240s
57.040s
55.787s
56.530s
60.010s
60.187s
324.227s
56.377s
55.337s
54.110s
56.164s
59.919s
493.468s
63.876s
57.389s
55.553s
54.908s
56.828s
再次丢弃异常值,这给出了 57.9 秒的平均运行时间和 3.6 秒的标准偏差。
所以这两个版本在统计上无法区分运行时间。
谁能指出我做错了什么?编译器吐出来的“盈利阈值”不是我想的意思吗?我非常感谢人们能给我的任何帮助,过去一周我一直在努力解决这个问题。
编辑:
我实现了@nilspipenbrinck 建议的更改,它似乎奏效了。我将矢量化循环插入一个函数中,并多次调用该函数。无矢量化的相对运行时间现在为 24.0s(<0.1s 的 sigma),而矢量化的相对运行时间为 20.8s(<0.2s 的 sigma),或者速度提高了 13%。没有我希望的那么多,但至少现在我知道它的工作原理!感谢您花时间查看我的问题并写下答案,我真的很感激。
最佳答案
你不会做太多算术运算。因此,测试代码的运行时间受内存限制。例如。您花费大部分时间在 CPU 和内存之间移动数据。
此外,您的 n 非常大,有 2^29 个元素。因此,您不会以任何方式从一级和二级缓存中获益。
如果您想看到 SSE 的改进,请使用较小的 n,这样您只需要接触 8 或 16 KB 的数据。还要确保数据是“热的”,例如它最近被 CPU 访问过。这样,数据就不必从主内存中移出,而是从缓存中移出,速度要快几个数量级。
作为替代方案,您还可以做更多的很多算术运算。这将使内存预取系统有机会在您利用 CPU 进行数学运算时在后台从主内存中获取数据。
总结:如果算法速度快于系统移动内存的速度,您将看不到任何好处。内存访问时间将成为瓶颈,您使用 SSE 指令集节省的几个周期将在内存访问时序的噪音中丢失。
关于c - GCC 自动矢量化对运行时没有影响,即使假定为 "profitable",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26945981/
我是 python 的新手。我试图找到我的文本的频率分布。这是代码, import nltk nltk.download() import os os.getcwd() text_file=open(
我对安卓 fragment 感到困惑。我知道内存 fragment 但无法理解什么是 android fragment 问题。虽然我发现很多定义,比如 Android fragmentation re
尝试对 WordPress 进行 dockerise 我发现了这个场景: 2个数据卷容器,一个用于数据库(bbdd),另一个用于wordpress文件(wordpress): sudo docker
这个问题已经有答案了: From the server is there a way to know that my page is being loaded in an Iframe (1 个回答)
我正在玩小型服务器,试图对运行在其上的服务进行docker化。为简化起见,假设我必须主要处理:Wordpress和另一项服务。 在Docker集线器上有许多用于Wordpress的图像,但是它们似乎都
我想要发生的是,当帐户成功创建后,提交的表单应该消失,并且应该出现一条消息(取决于注册的状态)。 如果成功,他们应该会看到一个简单的“谢谢。请检查您的电子邮件。” 如果不是,那么他们应该会看到一条适当
就是这样,我需要为客户添加一个唯一标识符。通过 strip 元数据。这就是我现在完全构建它的方式,但是我只有最后一部分告诉我用户购买了哪个包。 我试着看这里: Plans to stripe 代码在这
我有一个类将执行一些复杂的操作,涉及像这样的一些计算: public class ComplexAction { public void someAction(String parameter
这个问题已经有答案了: maven add a local classes directory to module's classpath (1 个回答) 已关闭10 年前。 我有一些不应更改的旧 E
我使用 fragment 已经有一段时间了,但我经常遇到一个让我烦恼的问题。 fragment 有时会相互吸引。现在,我设法为此隔离了一个用例,它是这样的: Add fragment A(也使用 ad
我的 html 中有一个 ol 列表,上面有行条纹。看起来行条纹是从数字后面开始的。有没有办法让行条纹从数字开始? 我已经包含了正在发生的事情的片段 h4:nth-child(even) {
如何仅使用 css 将附加图像 html 化? 如果用纯 css 做不到,那我怎么能至少用一个图像来做 最佳答案 这不是真正的问题,而是您希望我们为您编写代码。我建议您搜索“css breadcrum
以下是 Joshua 的 Effective Java 的摘录: If you do synchronize your class internally, you can use various te
在这里工作时,我们有一个框向业务合作伙伴提供 XML 提要。对我们的提要的请求是通过指定查询字符串参数和值来定制的。其中一些参数是必需的,但很多不是。 例如,我们要求所有请求都指定一个 GUID 来标
我有 3 个缓冲区,其中包含在 32 位处理器上运行的 R、G、B 位数据。 我需要按以下方式组合三个字节: R[0] = 0b r1r2r3r4r5r6r7r8 G[0] = 0b g1g2g3g4
我最近发现了关于如何使用 History.js、jQuery 和 ScrollTo 通过 HTML5 History API 对网站进行 Ajax 化的要点:https://github.com/br
我们有一个 Spring Boot 应用程序,由于集成需要,它变得越来越复杂——比如在你这样做之后发送一封电子邮件,或者在你之后广播一条 jms 消息等等。在寻找一些更高级别的抽象时,我遇到了 apa
我正在尝试首次实施Google Pay。我面临如何指定gateway和gatewayMarchantId的挑战。 我所拥有的是google console帐户,不知道在哪里可以找到此信息。 priva
昨天下午 3 点左右,我为两个想要从一个 Azure 帐户转移到另一个帐户的网站设置了 awverify 记录。到当天结束时,Azure 仍然不允许我添加域,所以我赌了一把,将域和 www 子域重新指
我正在使用terms facet在elasticsearch服务器中获取顶级terms。现在,我的标签"indian-government"不被视为一个标签。将其视为"indian" "governm
我是一名优秀的程序员,十分优秀!