如这个问题所示,对齐方式可能大于类型的大小,只是不能创建它的数组。但是,您可以创建一个 char[alignof(T)] 和reinterpret_cast 数组以在其中插入元素。
所以问题就变成了,在某些情况下,alignof(T) > sizeof(T)会很有用吗?我唯一能想到的就是与 SIMD 边界对齐。
如何为 __m128 向量制作 fabs() ?
我是否必须使用符号位将原始向量乘以 1.0f/-1.0f ?
没有找到任何指令集来做到这一点。
我不需要 __m256 或 512。我正在搜索 __m128 数据类型
我需要一个非常快速的伪随机数生成器来用于我一直在进行的项目。到目前为止,我已经实现了 xorshift 算法,并且可以生成伪随机 u64。但是,我需要将这些 u64 转换为 0 到 1 范围内的浮点值。
由于某种原因,我无法接近我想要的行为;这让我感到困惑,因为我使用了与此处完全相同的方法。尽管我看到实现没有任何差异,但我得到了不同的结果。
let seeds: [u64; 64] = core::array::from_fn(|i| i as u64);
let bitshift12 = u64x64::splat(12);
let bitshift25 = u64x64::splat(25);
let bitshift27 = u64x64::splat(27);
let bitshift52 = u64x64::splat(52);
let mut random_states = Simd::from(seeds);
random_states ^= random_states >> bitshift12;
random_states ^= random_states << bitshift25;
random_states ^= random_states >> bitshift27;
random_states = random_states | ((u64x64::splat(1023) + u64x64::splat(0)) << bitshift52);
let mut generated = Simd::<f64, 64>::from_bits(random_states);
println!("{:?}", generated); …Run Code Online (Sandbox Code Playgroud) 我有一个 4D 向量:std::array<float, 4>
我想检查它的所有组件是否都在值范围内:0.0f <= X && X < 256.0f
如何检查向量分量是否超出此范围?我所需要的只是一个布尔值来知道整个向量是否通过测试。
我第一次尝试解决这个问题是下面的代码:
bool Check_If_Outside_2(std::array<float, 4> vec)
{
bool outside = false;
for (int i = 0; i < 4; i++)
if (vec[i] < VType(0) || vec[i] >= VType(256))
outside = true;
return outside;
}
Run Code Online (Sandbox Code Playgroud)
这导致了这个汇编器输出:
Check_If_Outside_2(std::array<float, 4ul>): # @Check_If_Outside_2(std::array<float, 4ul>)
vxorps xmm2, xmm2, xmm2
vucomiss xmm0, xmm2
setb al
vmovss xmm3, dword ptr [rip + .LCPI7_0] # xmm3 = mem[0],zero,zero,zero
vucomiss xmm0, xmm3
setae cl
or cl, …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用内在函数为NEON实现校验和计算代码(2的补码加法).目前的校验和计算正在ARM上进行.
我的实现从存储器一次取128位到NEON寄存器并进行SIMD(加法),结果从128位数字折叠成16位数.
一切看起来都很好,但我的NEON实现消耗的时间比ARM版本多.
ARM版本需要:0.860000 s NEON版本需要:1.260000 s
注意:
其他详情:
问题:
为什么NEON版本比ARM版本花费更多时间?(虽然我已经注意使用批次中具有最小循环的内在因素)
如何实现我想要实现的目标?(与NEON的效率)
有人可以指向我或分享一些使用ARM-NEON的互操作的示例实现(伪代码/算法/代码,而不是理论实现论文或会谈)吗?
任何帮助将非常感激.
这是我的代码:
uint16_t do_csum(const unsigned char * buff, int len)
{
int odd, count, i;
uint32x4_t result = veorq_u32( result, result), sum = veorq_u32( sum, sum);
uint16x4_t data, data_hi, data_low, data8;
uint16x8_t dataq;
uint16_t result16, disp[20] = {0,0,0,0,0,0,0,0,0,0};
if (len <= 0)
goto out;
odd = 1 & (unsigned long) buff;
if (odd) {
uint8x8_t data1 = veor_u8( data1, data1); …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用SSE内在函数的8个浮点数组的每个元素,只是为了学习如何使用它们.但是,当我尝试这样写时:
alignas(16) float Numbers[8] =
{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f};
__m128 Group1 = _mm_load_ps(Numbers);
__m128 Group2 = _mm_load_ps(Numbers + 4*sizeof(float));
__m128 Zero = _mm_setzero_ps();
__m128 Sum1 = _mm_add_ps(Group1, Group2); // Sum1 = Group1 + Group2
__m128 Sum2 = _mm_hadd_ps(Sum1, Zero); // Sum2[31:0] = Sum1[31:0] + Sum1[63:32]
// Sum2[63:32] = Sum1[95:64] + Sum1[127:96]
__m128 Sum3 = _mm_hadd_ps(Sum2, Zero); // Sum3[31:0] = Sum2[31:0] + Sum2[63:32]
float Result;
_mm_store_ss(&Result, Sum3);
Run Code Online (Sandbox Code Playgroud)
Result当它应该是28时,它出现了6.我一直在指这些内在函数的参考,但我无法找出我的逻辑在这里出了什么问题.有什么建议?
基于SSE浮点向量的减少,我试图对无符号长数组求和,但是很不幸,没有成功。
uint64_t vsum_uint64 (uint64_t *a, int n)
{
uint64_t sum; // lets say sum fits
__m128 vsum = _mm_set1_ps(0);
for (int i = 0; i < n; i += 2) { // 2 unit64 in single __m128
__m128 v = _mm_loadl_epi64(&a[i]);
vsum = _mm_add_epi64(vsum, v);
}
_mm_store_ss(&sum, vsum);
uint64_t *p = &vsum;
sum+=*(p+1);
// vsum = _mm_hadd_ps(vsum, vsum);
// vsum = _mm_hadd_ps(vsum, vsum);
return sum;
}
Run Code Online (Sandbox Code Playgroud)
这应该是正确的,但是gcc仍然无法编译它。我搜索了答案,但没有找到答案。
这就是gcc所说的:
main.cpp: In function ‘uint64_t vsum_uint64(const uint64_t*, int)’:
main.cpp:73:35: …Run Code Online (Sandbox Code Playgroud) 我一直在阅读最近推出的AVX-512指令,我觉得有一个我不理解的基本概念.SIMD对已执行乱序执行的超标量CPU有什么好处?
请考虑以下伪汇编代码.使用SIMD:
load 16 floats to register simd-a
load 16 floats to register simd-b
multiply register simd-a by simd-b as 16 floats to register c
store the results to memory
Run Code Online (Sandbox Code Playgroud)
这没有SIMD:
load a float to register a
load a float to register b
multiply register a and register b as floats to c
store register c to memory
load a float to register a (contiguous to prior load to a)
load a float to register b (contiguous to prior load …Run Code Online (Sandbox Code Playgroud) 我有int的向量,我需要找到并替换一些具有特定值的元素.两者都是一样的.
例如:为所有元素替换4到8.
我在c ++中尝试循环内存访问.但它对我来说仍然很慢.
更新:
我正在使用OpenCV Mat对象x86:
for (int i = 0; i < labels.rows; ++i) {
for (int j = 0; j < labels.cols; ++j) {
int& label = labels.at<int>(i, j);
if (label == oldValue) {
label = newValue;
}
}
}
Run Code Online (Sandbox Code Playgroud)
Mat.at() 函数只是在释放模式下通过指针返回值
template<typename _Tp> inline
_Tp& Mat::at(int i0, int i1)
{
CV_DbgAssert(dims <= 2);
CV_DbgAssert(data);
CV_DbgAssert((unsigned)i0 < (unsigned)size.p[0]);
CV_DbgAssert((unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()));
CV_DbgAssert(CV_ELEM_SIZE1(traits::Depth<_Tp>::value) …Run Code Online (Sandbox Code Playgroud) 我正在制作一个基本上利用SSE2优化此代码的代码:
double *pA = a;
double *pB = b[voiceIndex];
double *pC = c[voiceIndex];
for (int sampleIndex = 0; sampleIndex < blockSize; sampleIndex++) {
pC[sampleIndex] = exp((mMin + std::clamp(pA[sampleIndex] + pB[sampleIndex], 0.0, 1.0) * mRange) * ln2per12);
}
Run Code Online (Sandbox Code Playgroud)
在这:
double *pA = a;
double *pB = b[voiceIndex];
double *pC = c[voiceIndex];
// SSE2
__m128d bound_lower = _mm_set1_pd(0.0);
__m128d bound_upper = _mm_set1_pd(1.0);
__m128d rangeLn2per12 = _mm_set1_pd(mRange * ln2per12);
__m128d minLn2per12 = _mm_set1_pd(mMin * ln2per12);
__m128d loaded_a = _mm_load_pd(pA);
__m128d loaded_b = _mm_load_pd(pB); …Run Code Online (Sandbox Code Playgroud)