有没有更快的方法在一个128位xmm寄存器中存储两个x86 32位寄存器?
movd xmm0, edx
movd xmm1, eax
pshufd xmm0, xmm0, $1
por xmm0, xmm1
Run Code Online (Sandbox Code Playgroud)
因此,如果EAX为0x12345678且EDX为0x87654321,则xmm0中的结果必须为0x8765432112345678.
谢谢
__m128 a;
__m128 b;
Run Code Online (Sandbox Code Playgroud)
如何编码a != b?
用什么:_mm_cmpneq_ps或_mm_cmpneq_ss?
如何处理结果?
找不到足够的文档.
我有一大段代码,其中一部分包含这段代码:
result = (nx * m_Lx + ny * m_Ly + m_Lz) / sqrt(nx * nx + ny * ny + 1);
Run Code Online (Sandbox Code Playgroud)
我已经矢量化如下(一切都已经是float):
__m128 r = _mm_mul_ps(_mm_set_ps(ny, nx, ny, nx),
_mm_set_ps(ny, nx, m_Ly, m_Lx));
__declspec(align(16)) int asInt[4] = {
_mm_extract_ps(r,0), _mm_extract_ps(r,1),
_mm_extract_ps(r,2), _mm_extract_ps(r,3)
};
float (&res)[4] = reinterpret_cast<float (&)[4]>(asInt);
result = (res[0] + res[1] + m_Lz) / sqrt(res[2] + res[3] + 1);
Run Code Online (Sandbox Code Playgroud)
结果是正确的; 但是,我的基准测试显示矢量化版本较慢:
result到0直接(和完全除去这部分代码)降低了整个过程至2500毫秒鉴于矢量版本只包含一个集SSE乘法(而不是四个单独的FPU乘法)的,为什么会慢?FPU确实比SSE快,或者这里有混淆变量吗?
(我在移动Core i5上.)
我正在做一些统计计算.我需要它们快速,所以我重写了大部分内容以使用SSE.我对它很陌生,所以我想知道这里的正确方法是什么:
据我所知,SSE中没有log2或ln功能,至少不能达到4.1,这是我使用的硬件支持的最新版本.
是否更好:
我正在考虑为uint32_t实现8-ary heapsort.为此,我需要一个函数来选择8元素向量中的最大元素的索引,以便我可以将它与父元素进行比较,并有条件地执行swap和进一步的siftDown步骤.
(8 uint32_ts可以更改为例如16 uint32_ts或8 uint64_t或x86 SIMD可以有效支持的任何内容).
我有一些关于如何做到这一点的想法,但我正在寻找比非矢量化代码更快的东西,特别是我正在寻找一些能让我快速进行快速操作的东西.
我有clang ++ 3.3和Core i7-4670,所以我应该能够使用最新的x86 SIMD东西.
(顺便说一下:这是一个更大项目的一部分:https://github.com/tarsa/SortingAlgorithmsBenchmark,例如四元heapsort,所以在实施SIMD heapsort后我可以立即比较它们)
重复 - 问题是:计算x86 SIMD向量中最大元素索引的最有效方法是什么?
PS:这不是链接问题的重复 - 注意我要求的是最大元素的索引,而不仅仅是元素值.
我正在尝试加速多核架构上的矩阵乘法.为此,我尝试同时使用线程和SIMD.但我的结果并不好.我通过顺序矩阵乘法测试加速:
void sequentialMatMul(void* params)
{
cout << "SequentialMatMul started.";
int i, j, k;
for (i = 0; i < N; i++)
{
for (k = 0; k < N; k++)
{
for (j = 0; j < N; j++)
{
X[i][j] += A[i][k] * B[k][j];
}
}
}
cout << "\nSequentialMatMul finished.";
}
Run Code Online (Sandbox Code Playgroud)
我尝试将线程和SIMD添加到矩阵乘法中,如下所示:
void threadedSIMDMatMul(void* params)
{
bounds *args = (bounds*)params;
int lowerBound = args->lowerBound;
int upperBound = args->upperBound;
int idx = args->idx;
int i, j, k;
for (i …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用System.Numerics.Vector(T)来矢量化算法并利用CPU的SIMD操作.但是,我的矢量实现比我原来的实现要慢得多.有没有使用可能没有记录的Vector的技巧?这里的具体用途是尝试加速数据的kb.
不幸的是,我在其上找到的几乎所有文档都基于RyuJIT的预发布版本,我不知道有多少这些材料可以移植到.NET Native.
当我在Vector xor操作期间检查反汇编时,它显示:
00007FFB040A9C10 xor eax,eax
00007FFB040A9C12 mov qword ptr [rcx],rax
00007FFB040A9C15 mov qword ptr [rcx+8],rax
00007FFB040A9C19 mov rax,qword ptr [r8]
00007FFB040A9C1C xor rax,qword ptr [rdx]
00007FFB040A9C1F mov qword ptr [rcx],rax
00007FFB040A9C22 mov rax,qword ptr [r8+8]
00007FFB040A9C26 xor rax,qword ptr [rdx+8]
00007FFB040A9C2A mov qword ptr [rcx+8],rax
00007FFB040A9C2E mov rax,rcx
Run Code Online (Sandbox Code Playgroud)
为什么不使用xmm寄存器和SIMD指令呢?同样奇怪的是,SIMD指令是针对此代码的一个版本生成的,我没有明确地向量化,但它们从未被执行,有利于常规寄存器和指令.
我确保我在Release,x64,Optimize代码启用的情况下运行.我看到了x86编译的类似行为.我在机器级别的东西上有点新手,所以它可能只是在这里发生了一些我不能正确理解的东西.
Framework版本为4.6,Vector.IsHardwareAccelerated在运行时为false.
更新: "使用.NET Native工具链编译"是罪魁祸首.启用它会导致Vector.IsHardwareAccelerated == false; 禁用它会导致Vector.IsHardwareAccelerated == true.我已经确认,当禁用.NET Native时,编译器会使用ymm寄存器生成AVX指令.这导致了一个问题......为什么在.NET Native中没有启用SIMD?有什么办法可以改变吗?
更新Tangent:我发现自动SSE矢量化数组代码未被执行的原因是因为编译器插入了一条指令,该指令查看数组的起始位置是否低于最后一个元素之一的地址数组,如果是,只使用普通寄存器.我认为这必定是编译器中的一个错误,因为按照惯例,数组的开头应始终位于比其最后一个元素低的地址.它是测试每个操作数数组的内存地址的一组指令的一部分,我想确保它们不重叠.我已为此提交了Microsoft Connect错误报告:https://connect.microsoft.com/VisualStudio/feedback/details/1831117
我有一些适用于__m128值的代码.我在这些值上使用x86-64 SSE内在函数,我发现如果值在内存中未对齐,我会崩溃.这是由于我的编译器(在此实例中为clang)仅生成对齐的加载指令.
我是否可以指示我的编译器生成未对齐的加载,无论是全局加载还是某些值(可能带有某种注释)?
我首先得到未对齐值的原因是我试图节省内存.我有一个struct大致如下:
#pragma pack(push, 4)
struct Foobar {
__m128 a;
__m128 b;
int c;
};
#pragma pack(pop)
Run Code Online (Sandbox Code Playgroud)
然后我创建了这些结构的数组.数组中的第二个元素从36个字节开始,这不是16的倍数.
我知道我可以切换到数组表示的结构,或者删除打包编译指示(代价是将结构的大小从36增加到48字节); 但我也知道,未对齐的载荷现在并不那么昂贵,并且想先尝试一下.
更新以回答以下一些评论:
我的实际代码更接近于此:
struct Vector4 {
__m128 data;
Vector4(__m128 v) : data(v) {}
};
struct Foobar {
Vector4 a;
Vector4 b;
int c;
}
Run Code Online (Sandbox Code Playgroud)
然后我有一些实用功能,例如:
inline Vector4 add( const Vector4& a, const Vector4 &b ) {
return Vector4(_mm_add_ps(a.data, b.data));
}
inline Vector4 subtract( const Vector4& a, const Vector4& b ) {
return Vector4(_mm_sub_ps(a.data, b.data));
} …Run Code Online (Sandbox Code Playgroud) 我想用JavaScript编写需要大量数值计算的应用程序.但是,我对客户端JavaScript中有效的线性代数式计算的状态非常困惑.似乎有很多方法,但没有明确表明他们的准备情况.它们中的大多数似乎都限制了允许计算的向量和矩阵的大小.
显然允许GPU上的矢量和矩阵计算,但我不清楚其局限性.围绕此库尝试的 包装器似乎限制了矩阵和向量的大小.这是一个实际的限制(浏览器不支持其他任何东西)或只是开发限制(有人需要编写代码)?
WebCL是OpenCL的一个提议的浏览器级实现,但似乎停留在开发中.
Apple最近提出了一种名为WebGPU的 WebCL替代方案.到目前为止,有一个原型和演示,但我不清楚这是否会被广泛采用.
Mozilla已经推出了一个用于SIMD操作的API,但它只有实验支持.
JavaScript支持浏览器端的矢量化计算吗?
笔记:
我的问题不是"JavaScript中的数值计算有什么好的库",而是"JavaScrpt中的矢量化操作是否可行?" 可接受的答案将链接到在非实验性浏览器中工作的矢量化计算的演示.
我可能会对SIMD,矢量化和GPU计算感到困惑.我认为在这种情况下同义地使用它们是可以的,因为它们都允许通过使用专门的计算机硬件进行涉及高维向量的有效计算.
大多数C++编译器都支持SIMD(SSE/AVX)指令
_mm_cmpeq_epi32
Run Code Online (Sandbox Code Playgroud)
我的问题是这个函数没有标记为constexpr,虽然"语义上"没有理由不使用这个函数,constexpr因为它是一个纯函数.
有什么办法,我可以写我自己的版本(例如)_mm_cmpeq_epi32是constexpr?
显然我希望运行时的函数使用正确的asm,我知道我可以重新实现具有慢速函数的任何SIMD函数constexpr.
如果你想知道为什么我关心constexprSIMD功能.非constexprness具有传染性,这意味着我的任何使用SIMD功能的功能都不可能constexpr.
simd ×10
sse ×7
c++ ×4
x86 ×3
assembly ×2
intrinsics ×2
.net ×1
.net-native ×1
avx ×1
c ×1
constexpr ×1
javascript ×1
logarithm ×1
matrix ×1
optimization ×1
performance ×1
uwp ×1
vector ×1
x86-64 ×1