C++ C++;SSE2内在论
我刚刚了解到,有一种方法可以使用内部函数实现一些并行化。我找到了下面的代码,并想看一下,但我能理解很多。我试着用单精度进行运算,但我怎么能做到呢C++ C++;SSE2内在论,c++,gcc,parallel-processing,intrinsics,C++,Gcc,Parallel Processing,Intrinsics,我刚刚了解到,有一种方法可以使用内部函数实现一些并行化。我找到了下面的代码,并想看一下,但我能理解很多。我试着用单精度进行运算,但我怎么能做到呢 #include <stdio.h> #include <stdlib.h> #include <xmmintrin.h> inline double pi_4 (int n){ int i; __m128d mypart2,x2, b, c, one; double
#include <stdio.h>
#include <stdlib.h>
#include <xmmintrin.h>
inline double pi_4 (int n){
int i;
__m128d mypart2,x2, b, c, one;
double *x = (double *)malloc(n*sizeof(double));
double *mypart = (double *)malloc(n*sizeof(double));
double sum = 0.0;
double dx = 1.0/n;
double x1[2] __attribute__((aligned(16)));
one = _mm_set_pd1(1.0); // set one to (1,1)
for (i = 0; i < n; i++){
x[i] = dx/2 + dx*i;
}
for (i = 0; i < n; i+=2){
x1[0]=x[i]; x1[1]=x[i+1];
x2 = _mm_load_pd(x1);
b = _mm_mul_pd(x2,x2);
c = _mm_add_pd(b,one);
mypart2 = _mm_div_pd(one,c);
_mm_store_pd(&mypart[i], mypart2);
}
for (i = 0; i < n; i++)
sum += mypart[i];
return sum*dx;
}
int main(){
double res;
res=pi_4(128);
printf("pi = %lf\n", 4*res);
return 0;
}
#包括
#包括
#包括
内联双pi_4(int n){
int i;
__m128d mypart2,x2,b,c,一个;
double*x=(double*)malloc(n*sizeof(double));
double*mypart=(double*)malloc(n*sizeof(double));
双和=0.0;
双dx=1.0/n;
双x1[2]uuu属性_uuu((对齐(16));
one=_mm_set_pd1(1.0);//将one设置为(1,1)
对于(i=0;i
我正在考虑将所有内容从double改为float,并调用正确的内在函数,例如,而不是_mm_set_pd1->_mm_set_ps1。我不知道这是否会使程序从双精度变为单精度
更新
我试着像下面这样,但是我遇到了一个分割错误
#include <stdio.h>
#include <stdlib.h>
#include <xmmintrin.h>
inline float pi_4 (int n){
int i;
__m128 mypart2,x2, b, c, one;
float *x = (float *)malloc(n*sizeof(float));
float *mypart = (float*)malloc(n*sizeof(float));
float sum = 0.0;
float dx = 1.0/n;
float x1[2] __attribute__((aligned(16)));
one = _mm_set_ps1(1.0); // set one to (1,1)
for (i = 0; i < n; i++){
x[i] = dx/2 + dx*i;
}
for (i = 0; i < n; i+=2){
x1[0]=x[i]; x1[1]=x[i+1];
x2 = _mm_load_ps(x1);
b = _mm_mul_ps(x2,x2);
c = _mm_add_ps(b,one);
mypart2 = _mm_div_ps(one,c);
_mm_store_ps(&mypart[i], mypart2);
}
for (i = 0; i < n; i++)
sum += mypart[i];
return sum*dx;
}
int main(){
float res;
res=pi_4(128);
printf("pi = %lf\n", 4*res);
return 0;
}
#包括
#包括
#包括
内联浮点pi_4(整数n){
int i;
__m128车型年款第2部分,x2,b,c,1;
float*x=(float*)malloc(n*sizeof(float));
float*mypart=(float*)malloc(n*sizeof(float));
浮动总和=0.0;
浮点数dx=1.0/n;
浮点x1[2]uuu属性_uuu((对齐(16));
one=_mm_set_ps1(1.0);//将one设置为(1,1)
对于(i=0;i
还需要一些修复程序:
需要用4个元素声明x1
- 第二个for循环需要增加4(这就是导致SEGFULT的原因)
数组需要有4个赋值x1
#include <stdio.h>
#include <stdlib.h>
#include <xmmintrin.h>
inline float pi_4 (int n){
int i;
__m128 mypart2,x2, b, c, one;
float *x = (float *)malloc(n*sizeof(float));
float *mypart = (float*)malloc(n*sizeof(float));
float sum = 0.0;
float dx = 1.0/n;
float x1[4] __attribute__((aligned(16)));
one = _mm_set_ps1(1.0); // set one to (1,1,1,1)
for (i = 0; i < n; i++){
x[i] = dx/2 + dx*i;
}
for (i = 0; i < n; i+=4){
x1[0]=x[i]; x1[1]=x[i+1];
x1[2]=x[i+2]; x1[3]=x[i+3];
x2 = _mm_load_ps(x1);
b = _mm_mul_ps(x2,x2);
c = _mm_add_ps(b,one);
mypart2 = _mm_div_ps(one,c);
_mm_store_ps(&mypart[i], mypart2);
}
for (i = 0; i < n; i++)
sum += mypart[i];
return sum*dx;
}
int main(){
float res;
res=pi_4(128);
printf("pi = %lf\n", 4*res);
return 0;
}
关于使用
malloc()
的一句话。我认为大多数实现都会按照SSE加载和存储的要求返回16字节边界对齐的内存,但这可能无法保证,因为m128不是C/C++类型(保证为“正常”类型对齐)。使用memalign()
或posix_memalign()
会更安全,您需要将uu m128d更改为u m128,否则您就走上了正确的道路。试试看它是否有效。它被称为“自动矢量化”。最近一个不错的编译器已经自动完成了这项工作,gcc也做到了。查看生成的机器代码。可能与@rhashimoto OK重复。让我试试看会发生什么。你有,你能解释一下这个代码背后的想法吗?你有其他的资料可以让我学到更多吗?@HansPassant是的,我读过gcc,是吗。。。大多数时候。。。但有时需要手工制作这些肮脏、有趣的把戏。我会检查另一个线程,看看它如何运行。如何查看生成的机器代码?gcc-S?
$ ./foo
pi = 3.141597