尝试开始使用SIMD指令,但在C中遇到错误(0xC0000005)

尝试开始使用SIMD指令,但在C中遇到错误(0xC0000005),c,cpu,C,Cpu,我正在尝试学习如何使用C语言中的SIMD指令。我决定开始使用SSE。我正在使用Windows 8.1,并在Windows环境中使用代码块进行编码。我的代码块设置设置为使用Intel i7(我有),因此启用SSE。我的程序编译得很好,但运行时一到,我就出错了。错误为“(0xC0000005)”。这是我的密码: #include <stdio.h> #include <stdlib.h> #include <math.h> #include <xmmintr

我正在尝试学习如何使用C语言中的SIMD指令。我决定开始使用SSE。我正在使用Windows 8.1,并在Windows环境中使用代码块进行编码。我的代码块设置设置为使用Intel i7(我有),因此启用SSE。我的程序编译得很好,但运行时一到,我就出错了。错误为“(0xC0000005)”。这是我的密码:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <xmmintrin.h>

float ScalarSSE(float *m1, float *m2) {

    float prod;
    int i;
    __m128 X, Y, Z;

    for(i=0; i<5; i+=4) {
        X = _mm_load_ps(&*m1);
        Y = _mm_load_ps(&*m2);
        X = _mm_mul_ps(X, Y);
        Z = _mm_add_ps(X, Z);
    }

    for(i=0; i<4; i++) {
        prod += Z[i];
    }

    return prod;

}

int main() {

    int i;
    float *s1 = calloc(1,sizeof (float));
    float *s2 = calloc(1,sizeof (float));

    for(i=0; i<100; i++) {
        *s1 = 2;
        *s2 = 2;
        float scalar_product_sse = ScalarSSE(s1, s2);
    }

    printf("Done");

    free (s1);
    free (s2);

}
#包括
#包括
#包括
#包括
浮子刻度ASE(浮子*m1,浮子*m2){
浮子;
int i;
__m128 X,Y,Z;

对于(i=0;i,这里为一个浮点分配空间:

float *s1 = calloc(1,sizeof (float));
然后在ScalarSE中访问多个浮点

也许这样做会有所帮助,但确定使用的确切数字会更好:

float *s1 = calloc(100,sizeof (float));
float *s2 = calloc(100,sizeof (float));
此外:

for(i=0; i<100; i++) {
    *s1 = 2;
    *s2 = 2;
    float scalar_product_sse = ScalarSSE(s1, s2);
}

for(i=0;i该代码有太多问题,我只想说明其中的一些问题,这些问题很可能是导致访问冲突的原因,并提供一个工作示例,然后您可以尝试根据自己的需要对其进行修改,因为很难理解您试图实现的目标

1) 内存对齐-采用16字节对齐的地址,您必须使用适当的内存分配函数,在该函数中可以指定对齐方式,如示例中所示,或将浮点封装在某种对齐结构中

2) 您正在使用未初始化的
Z
prod
值,因此添加后的结果将是未定义的

3) 如注释中所述,需要4个浮点数的向量,因此,如果您实际上只想加载一个值,那么在执行操作时分配1个浮点数是无效的。请参见,将一个浮点数加载到
\u m128
类型的所有四个值中,但由于
for
循环,无法理解最初的想法

下面是一个示例,基于您的代码,没有奇怪的for循环,它可以工作,我希望它足以实现您想要的:

#include <xmmintrin.h>
#include <stdio.h>
#include <malloc.h>

// This ensures the proper alignment
__declspec(align(16)) struct float_vector
{
    float a, b, c, d;
};

float ScalarSSE(float *m1, float *m2) {

    float prod = 0;
    int i;
    __m128 X, Y, Z;

    X = _mm_load_ps(m1); // This loads 4 values, so the pointer should point to an array of at least 4 floats
    Y = _mm_load_ps(m2); // This loads 4 values, so the pointer should point to an array of at least 4 floats
    Z = _mm_mul_ps(X, Y);

    for(i=0; i<4; i++) {
        prod += (reinterpret_cast<float*>(&Z))[i];
    }

    return prod;

}

int main() {

    float_vector s1 = { 2.0, 2.0, 2.0, 2.0 };
    float_vector s2 = { 2.0, 2.0, 2.0, 2.0 };

    float scalar_product_sse = ScalarSSE(&s1.a, &s2.a);
    printf("Done, result: %f\n", scalar_product_sse);

    return 0;
}
#包括
#包括
#包括
//这可确保正确对齐
__declspec(align(16))结构浮点向量
{
浮子a、b、c、d;
};
浮子刻度ASE(浮子*m1,浮子*m2){
浮点数=0;
int i;
__m128 X,Y,Z;
X=_mm_load_ps(m1);//这将加载4个值,因此指针应指向至少包含4个浮点的数组
Y=_mm_load_ps(m2);//这将加载4个值,因此指针应指向至少包含4个浮点的数组
Z=_mm_mul_ps(X,Y);

对于(i=0;iI无法使用调试模式,因为我不在项目中,也不知道如何在代码块中打开项目(这会给我错误)
&*m1
很奇怪。你是说
m1
。我看不到任何证据表明你正在对齐
s1
s2
。你不需要这样做吗?那么也许你应该学习如何使用调试模式?在你还没有掌握工具包的基本原理时,让我们对你的程序进行心理调试不是一个好方法。而且
\u-mm\u-load\u-ps
加载4个单精度值,压缩成128位值,16字节对齐。你知道
\u-mm\u-load\u-ps
做什么吗?你知道
\u-mm\u-mul\u-ps
做什么吗?你为什么不遵守规则?@DavidHeffernan代码实际上有很多问题,很难理解从何开始:)感谢您帮助Rob,我做了建议的更改,但不幸的是仍然得到相同的错误。是的,我知道我做了100次同样的事情,这是我想要做的,因为我希望计算不止一次。@user3423509,问题是如何访问ScalarSSE()中的浮点指针函数,第一个for循环打算做什么?如果你指的是位于程序顶部附近的那一个,它只是打算加载两个数字并对它们执行计算。我对它做了一点更改,另一个用户建议它显然是正确的,但仍然会得到相同的错误。你对
&*m1
的更改是“正确的”只是在这不是编译时错误的意义上。现在你有了一个从不使用循环变量的循环-这没有任何意义。在一个例子中,你可以在
main
中消除
For
循环,并打印结果。它肯定能满足我的预期目的(主要目的是编写工作代码,向我展示使用SIMD指令所需的内容。只需一个练习即可),虽然我的特定IDE似乎不想为一些错误成功地构建程序。主要的全局错误出现在第22行和第36行,我真的不知道发布错误的最优雅的方式是什么,所以我将自己尝试筛选它们,因为你们已经做了很多:)非常感谢。guys@user3423509您使用的IDE和编译器是什么?此示例在Visual Studio 2010上运行良好,初始代码没有编译,因为您不能仅访问_m128的元素,还有其他更好的方法来实现这一点。很抱歉回复太晚。我使用的是最新版本的代码块,我相信它是e GCC编译器。@user3423509我问了,因为您的初始代码有
prod+=Z[I]
部分没有在Visual Studio下编译,GCC编译它是有道理的,很奇怪。