AVX 与 SSE:预计会有更大的加速

2023-12-03

我预计 AVX 的速度比 SSE 快 1.5 倍左右。所有 3 个数组(3 个数组 * 16384 个元素 *4 字节/元素 = 196608 字节)应适合 Intel Core CPU (Broadwell) 上的 L2 缓存 (256KB)。

我应该使用任何特殊的编译器指令或标志吗?

编译器版本

$  clang --version
Apple LLVM version 9.0.0 (clang-900.0.38)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

编译行

$  make avx
clang -O3 -fno-tree-vectorize -msse -msse2 -msse3 -msse4.1 -mavx -mavx2 avx.c ; ./a.out 123
n: 123
  AVX Time taken: 0 seconds 177 milliseconds
vector+vector:begin int: 1 5 127 0

  SSE Time taken: 0 seconds 195 milliseconds
vector+vector:begin int: 1 5 127 0

avx.c

#include <stdio.h>
#include <stdlib.h>
#include <x86intrin.h>
#include <time.h>
#ifndef __cplusplus
#include <stdalign.h>   // C11 defines _Alignas().  This header defines alignas()
#endif
#define REPS 50000
#define AR 16384

// add int vectors via AVX
__attribute__((noinline)) 
void add_iv_avx(__m256i *restrict a, __m256i *restrict b, __m256i *restrict out, int N) {

    __m256i *x = __builtin_assume_aligned(a, 32);
    __m256i *y = __builtin_assume_aligned(b, 32);
    __m256i *z = __builtin_assume_aligned(out, 32);

    const int loops = N / 8; // 8 is number of int32 in __m256i
    for(int i=0; i < loops; i++) { 
        _mm256_store_si256(&z[i], _mm256_add_epi32(x[i], y[i]));
    }
}

// add int vectors via SSE; https://en.wikipedia.org/wiki/Restrict
__attribute__((noinline)) 
void add_iv_sse(__m128i *restrict a, __m128i *restrict b, __m128i *restrict out, int N) {

    __m128i *x = __builtin_assume_aligned(a, 16);
    __m128i *y = __builtin_assume_aligned(b, 16);
    __m128i *z = __builtin_assume_aligned(out, 16);

    const int loops = N / sizeof(int);
    for(int i=0; i < loops; i++) { 
        //out[i]= _mm_add_epi32(a[i], b[i]); // this also works
        _mm_storeu_si128(&z[i], _mm_add_epi32(x[i], y[i]));
    } 
}

// printing
void p128_as_int(__m128i in) {
    alignas(16) uint32_t v[4];
    _mm_store_si128((__m128i*)v, in);
    printf("int: %i %i %i %i\n", v[0], v[1], v[2], v[3]);
}

__attribute__((noinline)) 
void debug_print(int *h) {
    printf("vector+vector:begin ");
    p128_as_int(* (__m128i*) &h[0] );
}

int main(int argc, char *argv[]) {
    int n = atoi (argv[1]);
    printf("n: %d\n", n);

    int *x,*y,*z;
    if (posix_memalign((void**)&x, 32, 16384*sizeof(int))) { free(x); return EXIT_FAILURE; }
    if (posix_memalign((void**)&y, 32, 16384*sizeof(int))) { free(y); return EXIT_FAILURE; }
    if (posix_memalign((void**)&z, 32, 16384*sizeof(int))) { free(z); return EXIT_FAILURE; }
    x[0]=0; x[1]=2; x[2]=4;
    y[0]=1; y[1]=3; y[2]=n;

    // touch each 4K page in x,y,z to avoid copy-on-write optimizations
    for (int i=512; i<AR; i+= 512) { x[i]=1; y[i]=1; z[i]=1; }

    // warmup
    for(int i=0; i<REPS; ++i) { add_iv_avx((__m256i*)x, (__m256i*)y, (__m256i*)z, AR); }
    // AVX
    clock_t start = clock();
    for(int i=0; i<REPS; ++i) { add_iv_avx((__m256i*)x, (__m256i*)y, (__m256i*)z, AR); }
    int msec = (clock()-start) * 1000 / CLOCKS_PER_SEC;
    printf("  AVX Time taken: %d seconds %d milliseconds\n", msec/1000, msec%1000);
    debug_print(z);

    // warmup
    for(int i=0; i<REPS; ++i) { add_iv_sse((__m128i*)x, (__m128i*)y, (__m128i*)z, AR); }
    // SSE
    start = clock();
    for(int i=0; i<REPS; ++i) { add_iv_sse((__m128i*)x, (__m128i*)y, (__m128i*)z, AR); }
    msec = (clock()-start) * 1000 / CLOCKS_PER_SEC;
    printf("\n  SSE Time taken: %d seconds %d milliseconds\n", msec/1000, msec%1000);
    debug_print(z);

    return EXIT_SUCCESS;
}

问题是您的数据不适合 L1 缓存。 Broadwell的L1带宽远大于L2带宽。 L1 带宽足够大,可以在每个 CPU 周期加载两个 32 字节向量。因此,AVX 与 SSE 相比有更好的加速效果 如果您的数据集小得多,则可能是预期的。但请注意 L1 读/写组合带宽小于 2*32(r)+32(w)=96 个字节/周期。 实际上,每个周期 75 个字节是可能的,请参见here.

第二张图为this页面显示,L2 带宽确实要小得多: 当 Test_block_size=128KB(=每核 32KB)时,带宽为 900GB/s。 当 Test_block_size=1MB(=每核 256KB)时,带宽仅为 300GB/s。 (请注意,Haswell 4770k 与 Broadwell 具有或多或少相同的 L1 和 L2 缓存架构。)

尝试减少AR到 2000 并增加NREP到 1000000,看看 SSE 与 AVX 加速相比会发生什么情况。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AVX 与 SSE:预计会有更大的加速 的相关文章

  • 如果 PyPy 快 6.3 倍,为什么我不应该使用 PyPy 而不是 CPython?

    我已经听到很多关于PyPy http en wikipedia org wiki PyPy项目 他们声称它比现有技术快 6 3 倍CPython http en wikipedia org wiki CPython口译员开启他们的网站 ht
  • VBS 与 PowerShell:哪个更轻?

    如果我需要一个可以在系统中以最少的努力执行的脚本 我会选择哪个 通过查看任务管理器中的进程 内存 私有工作集 wscript exe 2 068Kpowershell exe 33 144K Thanks 这里存在工作守恒定律 如果机器做的
  • Pandas apply 与 np.vectorize 从现有列创建新列的性能

    我正在使用 Pandas 数据框 并希望创建一个新列作为现有列的函数 我还没有看到关于之间速度差异的很好的讨论df apply and np vectorize 所以我想我会在这里问 熊猫apply 功能很慢 根据我的测量 在一些实验中如下
  • cmd 和 workbench mysql 查询性能差异

    我有两个问题 正如我的标题 哪一个对于对大量数据运行大型查询更有效 我查看了 MySQL 文档 其中解释了工作台的性能https www mysql com products workbench performance https www
  • 与 StackExchange.Redis 并行执行?

    我有一个 100 万件商品的商店List
  • 变量查找:为什么变量的 ** 比值的慢得多

    我读过关于math sqrt比 今天我尝试了 但有趣的不是两者之间的时差 而是两者之间的时差 与变量和 具有值 value1 10 1 value2 0 5 timeit value1 value2 1000000 loops best o
  • 在 Windows 10 家庭版上运行性能配置文件

    我正在尝试在 Windows 10 上运行 IIS Express 的 Visual Studio 2017 探查器 但我遇到了一些麻烦 当我尝试安装所有必需的 IIS 组件时 我注意到我缺少一些组件 因为我运行的是 Windows 10
  • 为什么嵌套权重对性能不利?备择方案?

    我写了几个布局文件 其中使用了layout weight属性来创建不同视图之间的比率 在某些时候 我开始收到有关嵌套权重的 lint 警告 所以 我想知道为什么嵌套权重对性能不利 以及是否有一种更有效的方法来创建视图尺寸之间的恒定比率 该比
  • 最佳 SSE 无符号 8 位比较

    我试图找到使用 SSE 最高 SSE 4 2 执行 8 位无符号比较的最佳方法 我正在处理的最常见情况是比较 gt 0U 例如 mm cmpgt epu8 v mm setzero si128 1 当然 这也可以被认为是对非零的简单测试 但
  • 性能:Matlab 与 Python

    我最近从Matlab to Python 在转换我的一个冗长代码时 我惊讶地发现Python非常慢 我分析并追踪了一个函数占用时间的问题 该函数是从我的代码中的各个位置调用的 作为递归调用的其他函数的一部分 探查器建议300两个地方都调用了
  • ASM 中从小端到大端的快速转换

    我在 C 中有一个 uint 类型数组 在检查程序是否在小端机器上运行后 我想将数据转换为大端类型 因为数据量可能会变得非常大 但总是均匀的 所以我想考虑将两个 uint 类型作为 ulong 类型 以获得更好的性能并在 ASM 中对其进行
  • 当我提前知道可迭代类的长度时,我可以加速它吗?

    PEP 424 https www python org dev peps pep 0424 在 理由 中提到 能够根据预期大小预先分配列表 如估计的那样 length hint 可以是一个重大的优化 据观察 CPython 运行某些代码的
  • 编码/设计通用线程安全限制器(即将 X() 每秒执行多次)

    我计划设计一个类来将函数的执行限制在指定时间内的给定数量 例如 最大处理量1 秒内 5 个文件 它应该是线程安全的并且性能影响应该最小 你会如何设计这样一个类 我有几个想法 但对我来说 没有一个是正确的 是否有任何已知的设计模式可以完成此类
  • 对齐类型并按值传递参数

    按值传递对齐类型或具有对齐类型的结构不适用于某些实现 这会破坏 STL 容器 因为某些方法 例如 resize 按值获取参数 我使用 Visual Studio 2008 运行了一些测试 但不完全确定按值传递何时以及如何失败 我主要关心的是
  • 帮助我改进更多 SSE2 代码

    我正在寻找一些帮助来改进 core2 cpu 上的双线性缩放 sse2 代码 在我的 Atom N270 和 i7 上 此代码比 mmx 代码快大约 2 倍 但在 core2 cpu 下它只等于 mmx 代码 代码如下 void Conve
  • 使用带有不匹配索引的 pandas .loc 时内存爆炸+分配导致重复轴错误

    这是一个观察将 pandas 单元格与条件连接起来的最 Pythonic 方法 https stackoverflow com questions 69313521 most pythonic way to concatenate pand
  • Java:输入/使用“try-catch”块的开销?

    这个问题说明了一切 尽管命中率不是很高 我测得速度慢了 1 5 倍到 2 倍 但使用 try catch 的字节码和不使用 try catch 的字节码之间没有区别 那么是什么让它通常变慢呢 PL 请注意 问题不是抛出异常的开销 而是进入
  • 从高斯分布中采样随机值的最快方法是什么?

    The Box Muller 变换 http en wikipedia org wiki Box E2 80 93Muller transform 是一种从高斯分布中采样随机值的优雅且性能合理的方法 我正在寻找一种用 C 编写 清晰的更快方
  • 基准测试:PostgreSQL 上的 bigint 与 int

    我想提高数据库性能 在一个项目中 所有表都来自int to bigint 我认为这不仅在存储方面是一个糟糕的选择 因为int需要4 bytes and bigint需要8 bytes 但也与性能有关 所以我创建了一个小表1000万条目 其中
  • 将 HTML 字符串加载到 UIWebView 中的延迟

    我在导航控制器中有两个视图控制器 第一个视图控制器有一个带有按钮的菜单 按下此按钮将移动到第二个视图控制器并将 html 字符串加载到 UIWebView 中 没有其他东西被加载到 webview 中 只是一个简单的 NSString 其中

随机推荐

  • 如何动态增加 UITableViewCell 的高度

    我有一个 UITableView 其中包含 UITableViewCells 列表 我在方法中设置了 UITableViewCells 的高度 CGFloat tableView UITableView tableView heightFo
  • 在 Plotly 中悬停/单击时更改整个迹线的颜色

    我在绘图中绘制了当前图形 下面的 jupyter 笔记本代码 并希望创建这样的效果 当您将鼠标悬停或单击每个迹线时 整个迹线将以不同的颜色突出显示 在本例中为红色 我尝试从 SOF 中实现这些示例 Python 中的 Plotly 如何突出
  • 根据泛型类型调度不同的函数

    我想编写一个函数 让我分派传入的泛型类型 我不关心运行时值 只关心编译时类型 const value any const x DateTime parseAs
  • 在 C++ 中以特定间隔速率调用方法

    这真的让我很恼火 因为我以前做过 大约一年前 我一辈子都不记得那是什么图书馆了 基本上 问题是我希望能够以指定的时间间隔调用某个方法一定次数或一定时间段 一个例子是我想从现在开始调用方法 x 10次 每0 5秒一次 或者 从现在开始调用方法
  • 当我们删除一个项目时,字典会调整大小吗?

    在Python中 当我们从字典中删除一个项目时 字典会调整大小还是重建字典表 从一些网站和博客中我了解到 当我们从字典中删除一个项目时 Python会在删除的键中插入一个虚拟键来填充字典条目 稍后 Python将通过调用一些清理函数来清理虚
  • 密钥库类型:使用哪一种?

    通过查看文件java security of my JRE 我看到默认使用的密钥库类型设置为JKS Here 有一个可以使用的密钥库类型的列表 有推荐的密钥库类型吗 不同密钥库类型的优点 缺点是什么 与您链接到的标准名称列表中列出的类型相比
  • 缩放以显示 bing 地图中的所有位置

    假设我有 3 个图钉 1 加利福尼亚州 2 佛罗里达州 3 纽约 为了让这三个人都可见 我必须缩小到足够远才能看到整个国家 但可以说我有 1 加利福尼亚州 2 内华达州 3 德克萨斯州 我必须缩小才能覆盖美国的西南角 Windows Pho
  • Derby 数据库表列名称格式在查询中不一致

    当查询 Derby 数据库时 我发现对于某些表 我必须双引号列名并使用表名来限定列名 但对于其他一些表 我不需要 这些表会发生什么 如何使所有表相同并且可以在没有双引号和表名限定符的情况下查询它们 我正在使用 NetBeans IDE 的
  • d3.js V3 力定向图和未链接的节点

    我正在做我的第一个数据可视化项目 更多的是为了练习 学习 d3 js 因为数据可视化是我感兴趣的 我的第一个项目是制作力向图 该数据集是与其毗邻州相关的 50 个州 源是州 目标是边界州 夏威夷和阿拉斯加没有接壤的州 如果我在 csv 文件
  • 无法在 NetBeans IDE 中建立与 MySQL 的连接

    当我使用 Hibernate 创建新的 Web 项目时 我打开新建连接向导 选择 MySQL 连接器 J 驱动程序 选项 连接器 jar 出现在驱动程序文件列表中 按下一步按钮 设置主机 127 0 0 1 端口 3306 数据库名称 用户
  • 单击时关闭菜单

    我想通过单击链接或单击菜单外部来关闭菜单 为了让事情变得美好和轻松 我不想使用 jQuery 我该怎么做
  • 如果 Int 不能为 null,那么 null.asInstanceOf[Int] 是什么意思?

    作为测试 我写了这段代码 object Ambig extends App def f x Int println Int def f x String println String f null asInstanceOf Int f nu
  • 乳胶打印单斜杠、反斜杠r、反斜杠n

    我希望 tex 文件中的以下行 按原样 打印 while tmp 0 r tmp 0 n tmp 当我将它包装在 verb 命令中时 如下所示 verb while tmp 0 r tmp 0 n tmp 它不起作用 我得到 Undefin
  • MS Access:将参数从一种访问形式传递到另一种访问形式

    我有一个表格和一个按钮 我想通过单击按钮打开另一个表单 并将参数从父表单传递到子表单 子表单的 RecordSource 有参数 我该怎么做 您可以通过引用表单的对象来引用调用表单的任何属性 我不会用 表单属性的符号 我讨厌它 所以如果你想
  • Reportlab - 将两个段落添加到一个表格单元格中

    我有一个表 其构建如下 styleN styles Normal data table row ID Some Information data append table row table row table row append Par
  • 动态添加后突出显示表格行

    看看如何在使用 jquery 动态添加表行后突出显示它 我的代码似乎添加行没有问题 但它没有突出显示正确的行 jquery opponents tr last after tr td data td td more data td tr e
  • 正则表达式删除单行 SQL 注释 (--)

    问题 谁能给我一个可以从 SQL 语句中删除单行注释的有效正则表达式 C VB NET 我的意思是这些评论 This is a comment 不是那些 this is a comment 因为我已经可以处理明星评论了 我做了一个小解析器
  • 如何在 TypeScript 中向日期、字符串、数组、数字等添加方法

    如何告诉 TypeScript 对日期 数字 字符串等本机类型的添加 例如 我想要编译以下内容 示例来自http sugarjs com dates var date Date Date create tomorrow I get a co
  • 如何重定向到子文件夹,然后将子文件夹链接重写到 htaccess 中的根目录?

    如果这个问题是重复的 我很抱歉 但我在网上查找的所有内容都让我很困惑 所以我再次发布这个问题来指定我的需求 因为我希望我的网站结构干净 所以我想将内容与配置分开 所以我将所有页面放在 app文件夹 很像 Rails 应用程序 网站的结构大致
  • AVX 与 SSE:预计会有更大的加速

    我预计 AVX 的速度比 SSE 快 1 5 倍左右 所有 3 个数组 3 个数组 16384 个元素 4 字节 元素 196608 字节 应适合 Intel Core CPU Broadwell 上的 L2 缓存 256KB 我应该使用任