我正在编写一个生成LLVM IR指令的编译器.我正在广泛地使用矢量.
我希望能够将向量中的所有元素相加.现在我只是单独提取每个元素并手动添加它们,但它让我觉得这正是硬件应该能够帮助的东西(因为它听起来像一个非常常见的操作).但似乎并没有做到这一点.
最好的方法是什么?我正在使用LLVM 3.2.
使用VBROADCASTS命令在AVX中很容易,如果值是double或float,则在SSE中很容易.
如何向Delphi ASM中的XMM寄存器中的每个插槽广播一个8位值?
我需要水平添加一个__m128i16 x epi8值.XOP指令会使这个变得微不足道,但我没有这些指令.
目前的方法是:
hd = _mm_hadd_epi16(_mm_cvtepi8_epi16(sum), _mm_cvtepi8_epi16(_mm_shuffle_epi8(sum, swap)));
hd = _mm_hadd_epi16(hd, hd);
hd = _mm_hadd_epi16(hd, hd);
Run Code Online (Sandbox Code Playgroud)
SSE4.1有更好的方法吗?
我正在尝试使用simd内部函数在C中编程矩阵乘法。我非常确定自己的实现,但是执行时,我会从所得矩阵系数的第5位开始出现一些数字错误。
REAL_T只是具有typedef的浮点数
/* This is my matmul Version with simd, using floating simple precision*/
void matmul(int n, REAL_T *A, REAL_T *B, REAL_T *C){
int i,j,k;
__m256 vA, vB, vC, vRes;
for (i=0; i<n; i++){
for (j=0; j<n; j++){
for (k=0; k<n; k= k+8){
vA = _mm256_load_ps(&A[i*n+k]);
vB = _mm256_loadu_ps(&B[k*n+j]);
vC = _mm256_mul_ps(vA, vB);
vC = _mm256_hadd_ps(vC, vC);
vC = _mm256_hadd_ps(vC, vC);
/*To get the resulting coefficient, after doing 2 hadds,
I have to get the first and the last element …Run Code Online (Sandbox Code Playgroud) 我正在寻找一种最佳方法来计算 a __m256ior中所有打包的 32 位整数的总和__m512i。为了计算n 个元素的总和,我经常使用log2(n) vpaddd和vpermd函数,然后提取最终结果。但是,这不是我认为的最佳选择。
编辑:在速度/周期减少方面最佳/最佳。
是否有指令或有效的无分支指令序列来计算无序(未排序)ZMM 的最大(或最小)元素的索引(而不是其值)?
数据类型并不重要 - 我更感兴趣的是知道是否有已建立的使用模式。
与已知解决方案相关的问题是,对于严格排序的 ZMM,可以使用 CMPPS、MOVMSKPS 和 TZCNT 来获取外部元素适合此列表的位置的索引(即 BSEARCH)
嗨我有以下代码:
public unsafe class MultiplyAndAdd : IDisposable
{
float[] rawFirstData = new float[1024];
float[] rawSecondData = new float[1024];
static int alignment = 32;
float[] alignedFirstData = new float[1024 + alignment / sizeof(float)];
int alignedFirstDataOffset;
GCHandle alignedFirstDataHandle;
float* alignedFirstDataPointer;
float[] alignedSecondData = new float[1024 + alignment / sizeof(float)];
int alignedSecondDataOffset;
GCHandle alignedSecondDataHandle;
float* alignedSecondDataPointer;
public IEnumerable<object[]> Data { get; set; }
public void Dispose()
{
this.alignedFirstDataHandle.Free();
this.alignedSecondDataHandle.Free();
}
//Calculate the offset that needs to be applied to ensure that the array …Run Code Online (Sandbox Code Playgroud) 我想对设置位的所有索引求和。
\nhttp://bitmath.blogspot.com/2023/01/weighted-popcnt.html?m=1 \n有一个有趣的实现:
\n// sum of indexes of set bits\nint A073642(uint64_t n)\n{\n return __popcnt64(n & 0xAAAAAAAAAAAAAAAA) +\n (__popcnt64(n & 0xCCCCCCCCCCCCCCCC) << 1) +\n (__popcnt64(n & 0xF0F0F0F0F0F0F0F0) << 2) +\n (__popcnt64(n & 0xFF00FF00FF00FF00) << 3) +\n (__popcnt64(n & 0xFFFF0000FFFF0000) << 4) +\n (__popcnt64(n & 0xFFFFFFFF00000000) << 5);\n}\nRun Code Online (Sandbox Code Playgroud)\n(Godbolt:针对 MSVC、GCC 和 clang 的 x86-64-v3(AVX2,如 Haswell)编译器生成的 asm,有趣的是,它自动矢量化了四个 popcount。)
\n但是,我正在寻找一种无需多次使用 popcount 即可实现的方法。
\n我尝试在装配中执行此操作。popcount 操作相当快,但它可以用较少数量的指令完成,因为在每个 popcount 中我们重复相同的阶段(特别是如果硬件 popcount 不可用,比如在 RISC-V 上,或者 Nehalem 之前的 x86) 。
\n这就像一个“位拼图\xe2\x80\x9d”,我可能应该使用一些智能掩码和汇编的基本指令(算术/逻辑运算、条件移动/设置/跳转),但我不\xe2\x80\ x99不知道怎么做。 …
assembly bit-manipulation x86-64 hammingweight micro-optimization
我想用Intel sse内在计算rms.像这样:
float rms( float *a, float *b , int l)
{
int n=0;
float r=0.0;
for(int i=0;i<l;i++)
{
if(finitef(a[i]) && finitef(b[i]))
{
n++;
tmp = a[i] - b[i];
r += tmp*tmp;
}
}
r /= n;
return r;
}
Run Code Online (Sandbox Code Playgroud)
但是如何检查哪些元素是NaN?以及如何计算n?
是否有任何仍然相关的CPU(Intel/AMD/Atom)不支持SSSE3指令?
没有SSSE3的最新CPU是什么?