Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 使用SIMD指令将代码转换为代码_Performance_Parallel Processing_Simd - Fatal编程技术网

Performance 使用SIMD指令将代码转换为代码

Performance 使用SIMD指令将代码转换为代码,performance,parallel-processing,simd,Performance,Parallel Processing,Simd,我正在准备考试,正在做一些没有仪器的练习。因此,我一直在给出这段代码,并想知道我是否已将代码转换为SIMD指令 代码 int A[100000]; int B[100000]; int C=0; for int(i=0; i < 100000; i++) C += A[i] * B[i]; inta[100000]; int B[100000]; int C=0; 对于int(i=0;i

我正在准备考试,正在做一些没有仪器的练习。因此,我一直在给出这段代码,并想知道我是否已将代码转换为SIMD指令

代码

int A[100000];
int B[100000];
int C=0;

for int(i=0; i < 100000; i++)
    C += A[i] * B[i];
inta[100000];
int B[100000];
int C=0;
对于int(i=0;i<100000;i++)
C+=A[i]*B[i];
既然没有余数,我们就不需要处理它。我们还假设它是一个128位寄存器,因此可以计算4个单精度浮点值

我的结果-使用SIMD

int A[100000];
int B[100000];
int C=0;

for int(i=0; i < 100000/4; i += 4)
    C += A[i] * B[i];
    C += A[i+1] * B[i+1];
    C += A[i+2] * B[i+2];
    C += A[i+3] * B[i+3];
inta[100000];
int B[100000];
int C=0;
对于int(i=0;i<100000/4;i+=4)
C+=A[i]*B[i];
C+=A[i+1]*B[i+1];
C+=A[i+2]*B[i+2];
C+=A[i+3]*B[i+3];

您认为使用SIMD指令而不是编写多线程程序有什么好处?

是的,提供的代码应使用功能强大的CPU和编译器编译成SIMD指令

在支持向量的处理器上,SIMD公开了可大大加速相同并行计算的硬件功能。例如,由于流式RAM访问,SIMD通常可以更好地利用单个内核上的缓存,假设正在处理的数据位于连续的内存区域中。使用多处理、缓存竞争和其他同步开销实际上可能会降低性能,因为不同的内核试图同时写入数据。这是对冯·诺依曼机器的内在提升,使其不必从共享系统内存中读取一条而不是四条单独的指令


并行执行这些算术运算的逻辑始终存在,但需要使用特定的SIMD指令。因此,SIMD倾向于在热循环中使用,在热循环中,手动调优具有整体优化意义。

是的,提供的代码应编译成具有功能CPU和编译器的SIMD指令

在支持向量的处理器上,SIMD公开了可大大加速相同并行计算的硬件功能。例如,由于流式RAM访问,SIMD通常可以更好地利用单个内核上的缓存,假设正在处理的数据位于连续的内存区域中。使用多处理、缓存竞争和其他同步开销实际上可能会降低性能,因为不同的内核试图同时写入数据。这是对冯·诺依曼机器的内在提升,使其不必从共享系统内存中读取一条而不是四条单独的指令


并行执行这些算术运算的逻辑始终存在,但需要使用特定的SIMD指令。因此,SIMD倾向于在热循环中使用,在热循环中,手动调整具有整体优化意义。

假设第二个循环中省略的花括号只是一个输入错误,而for循环中的输入错误,并且您询问浮点乘法,但您的代码显示整数数组,即使编译器看到它,也不会得到很好的矢量化。虽然编译器可能将A和B中的4个值作为单个指令分别加载,并在一条指令中执行4次乘法,但您的代码强制编译器提取4个乘积中的每一个并按顺序求和,从SIMD寄存器中获取单个值通常相当慢

如果另一方面你这么做了

float A[100000];
float B[100000];
float C0=0, C1=0, C2=0, C3=0;

for (size_t i=0; i < 100000/4; i += 4)
{
    C0 += A[i+0] * B[i+0];
    C1 += A[i+1] * B[i+1];
    C2 += A[i+2] * B[i+2];
    C3 += A[i+3] * B[i+3];
}
float C = (C0 + C1) + (C2 + C3);
float A[100000];
浮动B[100000];
浮点数C0=0,C1=0,C2=0,C3=0;
对于(尺寸i=0;i<100000/4;i+=4)
{
C0+=A[i+0]*B[i+0];
C1+=A[i+1]*B[i+1];
C2+=A[i+2]*B[i+2];
C3+=A[i+3]*B[i+3];
}
浮点数C=(C0+C1)+(C2+C3);
然后,一个好的编译器可以将其矢量化,因为现在它看到,在每个循环中,它加载两个SIMD寄存器,将它们相乘,然后它可以将结果添加到SIMD寄存器的和中,并且只提取这4个和,并在最后将它们全部相加

矢量化编译可以通过SIMD实现这一点,它不会改变单个和的计算顺序(FP数学不是关联的)。由于这个原因,编译器通常不允许更改FP Math的顺序(没有一些额外的标志允许它在技术上违反语言标准),因此上面的代码可以用SIMD指令精确表示,并且运行速度会快得多(事实上,我将把循环再放一个阶段,因为乘法将是一个瓶颈)

这是SIMD的一种技巧,您必须理解并思考如何用向量指令最好地实现该操作,然后编写代码以执行相同的操作序列,并希望编译器能够发现您所做的事情

或者,您可以自己使用内部函数编写向量指令,或者使用OpenMP或类似工具更明确地告诉编译器要做什么


在这种操作中,SIMD相对于线程的优势之一是,您在单个内核中使用了更多的硅元素……因此,您不会阻止另一个线程获得周期。在我们的计算网格上,我们通常在任何一台机器上运行多个单线程进程,以使所有内核始终处于繁忙状态……在这种情况下如果使用更多的内核进行此求和是一种错误的经济行为,那么您只会窃取另一个线程可以有效运行另一个作业的周期。

假设第二个循环中省略的大括号只是一个输入错误,而for循环中的输入错误,并且您询问浮点乘法,但代码显示的是整数数组,那么即使编译器看到它,也无法获得很好的矢量化。虽然编译器可能会将A和B中的4个值作为单个指令分别加载,并在一条指令中进行4次乘法,但您的代码会强制编译器提取4个乘积中的每一个,并按顺序求和,而从SIMD寄存器中获取单个值则是错误的通常相当慢

如果在oth上