c语言会自动生成simd,simd C语言编程开发

Tag: simd

从基于来源的指数转换为基于目的地的指数

我在一些C代码中使用AVX2指令。 VPERMD指令采用两个8整数向量a和idx并通过基于idx置换a来生成第三个向量dst 。 这似乎相当于dst[i] = a[idx[i]] for i in 0..7 。 我正在调用此源代码,因为该移动是基于源索引的。 但是,我有基于目的地forms的计算索引。 这对于设置数组是很自然的,相当于dst[idx[i]] = a[i] for i in 0..7 。 如何从基于源的表单转换为基于目标的表单? 一个示例测试用例是: {2 1 0 5 3 4 6 7} source-based form. {2 1 0 4 5 3 6 7} destination-based equivalent 对于这种转换,我留在ymm寄存器中,这意味着基于目标的解决方案不起作用。 即使我要单独插入每个,因为它只在常量索引上运行,你不能只设置它们。

霓虹灯比较

根据Neon文档: 如果对于通道的比较为真,则该通道中的结果将所有位设置为1。 如果通道的比较为假,则所有位都设置为零。 返回类型是无符号整数类型。 我写了一小段代码来检查这个,我观察结果为0和-1而不是0和1.任何人都可以告诉我这背后的原因吗? 码: float c1[4] = {12.0f,12.0f,12.0f,12.0f}; float c2[4] = {13.0f,12.0f,9.0f,12.0f}; float32x4_t t1,t2; uint32x4_t rq; t1 = vld1q_f32(c1); t2 = vld1q_f32(c2); rq = vceqq_f32(t1,t2); printf(“start\n”); for( int i = 0;i < 4; i++){ printf("%d\n",rq[i]); } printf("end\n"); 结果: start 0 -1 0 -1 end

边框检查图像处理

我想在处理图像处理中的任何滤镜时注意边界条件。我正在外推边框并创建新边界。例如,我有4×3输入: //Input int image[4][3] = 1 2 3 4 2 4 6 8 3 6 9 12 //Output int extensionimage[6][5] = 1 1 2 3 4 4 1 1 2 3 4 4 2 2 4 6 8 8 3 3 6 9 12 12 3 3 6 9 12 12 我的代码: #include #include #include […]

SSE字节和半字交换

我想使用SSE内在函数翻译此代码。 for (uint32_t i = 0; i > 16) & 0xFFFF) | (value << 16); } 是否有人知道执行16位字交换的内在函数?

使用SSE(x * x * x)+(y * y * y)进行乘法

我正在尝试使用SIMD优化此function,但我不知道从哪里开始。 long sum(int x,int y) { return x*x*x+y*y*y; } 反汇编函数如下所示: 4007a0: 48 89 f2 mov %rsi,%rdx 4007a3: 48 89 f8 mov %rdi,%rax 4007a6: 48 0f af d6 imul %rsi,%rdx 4007aa: 48 0f af c7 imul %rdi,%rax 4007ae: 48 0f af d6 imul %rsi,%rdx 4007b2: 48 0f af c7 imul %rdi,%rax 4007b6: 48 8d 04 02 […]

矢量*矩阵产品效率问题

正如Z boson 推荐的那样 ,我使用的是列主矩阵格式,以避免使用点积。 但是,在将矢量与矩阵相乘时,我没有看到避免它的可行方法。 矩阵乘法技巧需要有效提取行(或列,如果我们转置产品)。 为了将矢量乘以矩阵,我们因此转置: (b * A)^T = A^T * b^T A是矩阵, b是行向量,在被转置之后变为列向量。 它的行只是单个标量,矢量*矩阵乘积实现成为(非转置)矩阵A和b的列点积的低效实现。 有没有办法避免执行这些点产品? 我认为可以做到的唯一方法是涉及行提取,这对于列主矩阵格式来说是低效的。

从SIMD指令捕获SIGFPE

我试图清除浮点除以零标志以忽略该exception。 我期待着设置了标志(我相信默认行为没有变化,并在下面注释掉),我的error handling程序将触发。 但是, _mm_div_ss似乎没有提高SIGFPE。 有任何想法吗? #include #include #include #include static void sigaction_sfpe(int signal, siginfo_t *si, void *arg) { printf(“inside SIGFPE handler\nexit now.”); exit(1); } int main() { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_sigaction = sigaction_sfpe; sa.sa_flags = SA_SIGINFO; sigaction(SIGFPE, &sa, NULL); //_mm_setcsr(0x00001D80); // catch all FPE except divide by zero __m128 s1, […]

SSE对冲浮标练习

在处理SSE(AVX)中的整数和浮点数时,将所有整数转换为浮点数并仅使用浮点数是一个好习惯吗? 因为之后我们只需要一些SIMD指令,而我们需要使用的是添加和比较指令(

使用sse内在函数时如何摆脱循环?

__m128* pSrc1 = (__m128*) string; __m128 m0 = _mm_set_ps1(0); //null character while(1) { __m128 result = __m128 _mm_cmpeq_ss(*pSrc1, m0); //if character is \0 then break //do some stuff here pSrc1++; } 我有一个字符串,其长度可以是16的倍数。如果_mm_cmpeq_ss返回相等,我如何突破循环?

在`C`函数中定义`static const` SIMD变量

我有这种forms的函数(使用SSE从指数函数的最快实现 ): __m128 FastExpSse(__m128 x) { static __m128 const a = _mm_set1_ps(12102203.2f); // (1 << 23) / ln(2) static __m128i const b = _mm_set1_epi32(127 * (1 << 23) – 486411); static __m128 const m87 = _mm_set1_ps(-87); // fast exponential function, x should be in [-87, 87] __m128 mask = _mm_cmpge_ps(x, m87); __m128i tmp = _mm_add_epi32(_mm_cvtps_epi32(_mm_mul_ps(a, […]

Posts navigation

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个使用SIMD加速的C语言蒙特卡洛积分程序,用于计算二十维空间中的单位球的体积: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> #include <immintrin.h> #define N 20 // 维度 #define M 4 // SIMD宽度 double f(double *x) { // 被积函数,计算点(x[0], x[1], ..., x[N-1])是否在单位球内 double sum = 0; for (int i = 0; i < N; i++) { sum += x[i] * x[i]; } return sum < 1 ? 1 : 0; } double monte_carlo_integrate(int n) { // 使用蒙特卡洛方法求定积分 double s = 0; double x[N * M] __attribute__((aligned(32))); srand(time(NULL)); for (int i = 0; i < n / M; i++) { for (int j = 0; j < N * M; j++) { x[j] = (double)rand() / RAND_MAX * 2 - 1; // 生成随机点 } __m256d sum = _mm256_setzero_pd(); // 初始化累加器 for (int j = 0; j < N * M; j += 4) { __m256d v = _mm256_load_pd(&x[j]); // 加载四个点到向量寄存器中 v = _mm256_mul_pd(v, v); // 计算平方 sum = _mm256_add_pd(sum, v); // 向量累加 } double t[4] __attribute__((aligned(32))); _mm256_store_pd(t, sum); // 将向量结果存储到临时数组中 for (int j = 0; j < 4; j++) { s += t[j] < 1 ? 1 : 0; // 判断是否在单位球内,并累加到结果中 } } return pow(2, N) * s / n; } int main() { int n = 10000000; // 抽样点数 double result = monte_carlo_integrate(n); printf("result:%lf\n", result); return 0; } ``` 在这个程序中,我们使用了AVX2指令集来实现SIMD加速。首先,我们定义了一个宏`M`,表示每次处理的向量宽度。然后,我们定义了一个函数`f`,用于判断点`(x[0], x[1], ..., x[N-1])`是否在单位球内,和上面的代码相同。 接着,我们定义了一个函数`monte_carlo_integrate`,用于计算积分结果。在该函数中,我们首先定义了一个累加器`s`,并通过两个嵌套的`for`循环来抽取`n`个随机点。在内层循环中,我们生成随机点,并将其存放在一维数组`x`中。由于需要使用向量寄存器进行SIMD计算,因此我们将数组`x`扩展为二维数组,每行包含`M`个随机点。 然后,我们使用AVX2指令集中的向量指令来进行SIMD计算。首先,我们定义了一个向量累加器`sum`,并将其初始化为0。然后,我们使用`_mm256_load_pd`函数将四个随机点加载到一个向量寄存器中,并使用`_mm256_mul_pd`函数计算这些点的平方。接着,我们使用`_mm256_add_pd`函数对向量累加器进行累加。在每次循环结束时,我们使用`_mm256_store_pd`函数将向量结果存储到一个临时数组`t`中,然后使用一个循环来判断每个结果是否在单位球内,并将结果累加到`s`中。 最后,我们根据蒙特卡洛积分的公式,计算出积分结果,并将结果打印出来。 需要注意的是,在使用AVX2指令集时,需要保证数组的对齐方式为32字节对齐,否则导致性能下降。因此,在定义数组`x`和临时数组`t`时,我们使用了`__attribute__((aligned(32)))`来指定数组的对齐方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值