typedef float v4sf __attribute__ ((mode(V4SF)));
Run Code Online (Sandbox Code Playgroud)
这是在海湾合作委员会。有人知道等价语法吗?
VS 2010将显示__attribute__没有此类型的存储类,并且模式未定义。
我在网上搜索了一下,上面说
相当于
__attribute__( aligned( size ) )GCC 中的对于以前的 UNIX 开发人员或编写在多个平台上工作的代码的人来说,这很有帮助,在 GCC 中,您可以使用 属性(aligned(...))获得相同的结果
有关更多信息,请参阅此处: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Type-Attributes.html#Type-Attributes
完整的 GCC 代码在这里: http: //pastebin.com/bKkTTmH1
在详细说明细节之前,我有以下功能,
令 _e, _w 为大小相等的数组。令 _stepSize 为 float 类型。
void GradientDescent::backUpWeights(FLOAT tdError) {
AI::FLOAT multiplier = _stepSize * tdError;
for (UINT i = 0; i < n; i++){
_w[i] += _e[i]*multiplier
}
// Assumed that the tilecode ensure that _w.size() or _e.size() is even.
}
Run Code Online (Sandbox Code Playgroud)
这个函数很好,但是如果一个CPU有内在的,特别是对于这个例子,SSE4,那么下面的函数可以让我减少几秒钟的时间(对于相同的输入),即使-O3 gcc标志已经包含在两个和额外的-msse4a中为此添加了。
void GradientDescent::backUpWeights(FLOAT tdError) {
AI::FLOAT multiplier = _stepSize * tdError;
__m128d multSSE = _mm_set_pd(multiplier, multiplier);
__m128d* eSSE = (__m128d*)_e;
__m128d* wSSE = (__m128d*)_w;
size_t n = getSize()>>1;
for (UINT i = 0; i …Run Code Online (Sandbox Code Playgroud) 我有一个代码可以将一个向量围绕另一个向量旋转到给定角度。我使用四元数和这个快速公式来做到这一点。我编写了两个变体,使用和不使用 SIMD 编译器内在函数。
变体 1:
#include <xmmintrin.h>
#include <pmmintrin.h>
#include "test2.h"
static __v4sf cross_product_ (__v4sf a, __v4sf b)
{
__v4sf r1 = a * _mm_shuffle_ps (b, b, _MM_SHUFFLE (1, 3, 2, 0));
__v4sf r2 = b * _mm_shuffle_ps (a, a, _MM_SHUFFLE (1, 3, 2, 0));
__v4sf r = r1 - r2;
return _mm_shuffle_ps (r, r, _MM_SHUFFLE (1, 3, 2, 0));
}
static __v4sf rotate_vector_ (__v4sf base, __v4sf vect)
{
__v4sf base_re = _mm_shuffle_ps (base, base, 0);
__v4sf tmp …Run Code Online (Sandbox Code Playgroud) 我正在寻找计算以下函数的有效方法:
输入:__m128i data, uint8_t in;
输出:布尔值,指示是否有任何字节data是in。
我基本上是使用它们来为容量为 8 的字节实现空间/时间高效的堆栈。我最有效的解决方案是首先计算__m128i tmp所有字节为 的 a in。然后检查是否有任何字节tmp\xor data是零字节。
我一直在玩一些 x64 程序集和 XMM 寄存器来做一些浮点数学,我看到一些让我感到困惑的性能。
作为自学练习,我编写了一些 SSE 程序集来近似“sin”函数(使用泰勒级数),并在循环中从一些基本的 C++ 调用它以与标准库版本进行比较。代码如下,之后我粘贴了一些典型运行的输出。(我不是在寻找对代码或方法的批评,只是想了解性能数字)。
我不明白的是为什么使用“发布”构建,其中实际运行的程序集是相同的(我已经通过调试器进行了仔细检查),始终慢了大约 40 - 50 个周期。(取消对 LFENCE 指令的注释会为 Debug 和 Release 增加大约 100 个周期,因此增量保持不变)。作为一个额外的问题,为什么第一次迭代通常是数千次!!
我知道这些东西非常复杂,并且受到许多因素的微妙影响,但是作为潜在原因出现在我脑海中的一切都是没有意义的。
我已经在两次运行中检查了 MSCSR 标志,这在构建中也是相同的(默认值为 1f80h,它屏蔽了所有异常)。
知道什么会导致这种情况吗?我可以做哪些进一步的分析来更深层次地解决这个问题?
集会
_RDATA segment
pi real4 3.141592654
rf3 real4 0.1666666667
rf5 real4 0.008333333333
rf7 real4 0.0001984126984
_RDATA ends
_TEXT segment
; float CalcSin(float rads, int* cycles)
CalcSin PROC
; "leaf" function - doesn't use the stack or any non-volatile registers
mov r8, rdx ; Save the 'cycles' pointer …Run Code Online (Sandbox Code Playgroud) 我试图找到种子来散列最大可能长度的小写字母短字符串而不会发生冲突。我选择了 SSE 4.2 CRC32 来简化任务。对于长度为 4、5、6 的种子,在一些合理的小值内没有碰撞(我不能无限等待)。
#include <bitset>
#include <limits>
#include <iterator>
#include <iostream>
#include <x86intrin.h>
static std::bitset<size_t(std::numeric_limits<uint32_t>::max()) + 1> hashes;
static void findSeed()
{
uint8_t c[7];
const auto findCollision = [&] (uint32_t seed)
{
std::cout << "seed = " << seed << std::endl;
hashes.reset();
for (c[0] = 'a'; c[0] <= 'z'; ++c[0]) {
uint32_t hash0 = _mm_crc32_u8(~seed, c[0]);
for (c[1] = 'a'; c[1] <= 'z'; ++c[1]) {
uint32_t hash1 = _mm_crc32_u8(hash0, c[1]);
for (c[2] = 'a'; c[2] <= …Run Code Online (Sandbox Code Playgroud) 我正在努力让我的应用程序为 Apple Silicon 做好准备。我的应用程序目前使用适用于 Mac 的 SSE 指令和适用于 iOS 的等效 Neon 实现。
Apple 移植指南建议转向 Accelerate 框架,我现在还没有准备好。
有没有办法在 Apple 芯片的通用二进制文件中继续使用 SSE/neon(基于架构)?我可以看到 arm64_neon.h 不适用于 Apple Silicon。
我想知道在使用 SSE2 时如何有效地加载和存储变量。
在这个例子中,我想将pclmulqdq指令(进行较少的乘法,对多项式算术有用)与普通的 C 函数进行对比,所以我需要与标准函数相同的“调用约定”。
a 和 b 是 16 位有效位,结果将有 32 位有效位
#include <wmmintrin.h>
int GFpoly_mul_i(int a, int b) {
__m128i xa = _mm_loadu_si128( (__m128i*) a);
__m128i xb = _mm_loadu_si128((__m128i*) b);
__m128i r = _mm_clmulepi64_si128(xa, xb, 0);
_MM_ALIGN16 int result[4];
__m128i* ptr_result = (__m128i*)result;
_mm_store_si128(ptr_result, r);
return result[0];
}
Run Code Online (Sandbox Code Playgroud) 有没有办法转换以下代码:
int mask16 = 0b1010101010101010; // int or short, signed or unsigned, it does not matter
Run Code Online (Sandbox Code Playgroud)
到
__uint128_t mask128 = ((__uint128_t)0x0100010001000100 << 64) | 0x0100010001000100;
Run Code Online (Sandbox Code Playgroud)
所以要特别清楚,比如:
int mask16 = 0b1010101010101010;
__uint128_t mask128 = intrinsic_bits_to_bytes(mask16);
Run Code Online (Sandbox Code Playgroud)
或直接敷面膜:
int mask16 = 0b1010101010101010;
__uint128_t v = ((__uint128_t)0x2828282828282828 << 64) | 0x2828282828282828;
__uint128_t w = intrinsic_bits_to_bytes_mask(v, mask16); // w = ((__uint128_t)0x2928292829282928 << 64) | 0x2928292829282928;
Run Code Online (Sandbox Code Playgroud) 我正在尝试将 16 字节的内存加载到模块中的__m128i类型中std::arch:
#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
use std::arch::x86_64::__m128i;
fn foo() {
#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
use std::arch::x86_64::_mm_load_si128;
unsafe {
let mut f: [i8; 16] = [0; 16];
f[0] = 5;
f[1] = 66;
let g = _mm_load_si128(f as *const __m128i);
}
}
fn main() {
foo();
}
Run Code Online (Sandbox Code Playgroud)
我的代码导致错误:
error[E0605]: non-primitive cast: `[i8; 16]` as `*const __m128i`
--> src/main.rs:12:32
|
12 | let g = _mm_load_si128(f as *const __m128i);
| ^^^^^^^^^^^^^^^^^^^ an …Run Code Online (Sandbox Code Playgroud)