Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.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
C 无法使用SSE进行优化_C_Sse - Fatal编程技术网

C 无法使用SSE进行优化

C 无法使用SSE进行优化,c,sse,C,Sse,我正在测试SSE对Zip解密的一种变体。但是,未优化的代码性能更好 使用参数:-msse4-O3运行编译器会产生以下基准测试:- 正常测试:0.275,SSE测试:0.655 我尝试增加循环计数器,但基准没有太大变化。编译器正在进行哪些优化?我们是否应该使用SSE来匹配它 编辑:按照Jens的建议使用了墙时间,增加了循环迭代次数,并固定了printf格式 #include <stdio.h> #include <stdint.h> #include <smmintr

我正在测试SSE对Zip解密的一种变体。但是,未优化的代码性能更好

使用参数:-msse4-O3运行编译器会产生以下基准测试:-

正常测试:0.275,SSE测试:0.655

我尝试增加循环计数器,但基准没有太大变化。编译器正在进行哪些优化?我们是否应该使用SSE来匹配它

编辑:按照Jens的建议使用了墙时间,增加了循环迭代次数,并固定了printf格式

#include <stdio.h>
#include <stdint.h>
#include <smmintrin.h>
#include <time.h>

//  Windows
#ifdef _WIN32
#include <Windows.h>
double get_wall_time()
{
    LARGE_INTEGER time,freq;
    if (!QueryPerformanceFrequency(&freq))
    {
        //  Handle error
        return 0;
    }
    if (!QueryPerformanceCounter(&time))
    {
        //  Handle error
        return 0;
    }

    return (double)time.QuadPart / freq.QuadPart;
}

double get_cpu_time()
{
    FILETIME a,b,c,d;
    if (GetProcessTimes(GetCurrentProcess(),&a,&b,&c,&d) != 0)
    {
        //  Returns total user time.
        //  Can be tweaked to include kernel times as well.
        return
            (double)(d.dwLowDateTime |
            ((unsigned long long)d.dwHighDateTime << 32)) * 0.0000001;
    }
    else
    {
        //  Handle error
        return 0;
    }
}

//  Posix/Linux
#else
#include <sys/time.h>
double get_wall_time()
{
    struct timeval time;
    if (gettimeofday(&time,NULL))
    {
        //  Handle error
        return 0;
    }

    return (double)time.tv_sec + (double)time.tv_usec * .000001;
}

double get_cpu_time()
{
    return (double)clock() / CLOCKS_PER_SEC;
}
#endif


static void test_sse()
{
    double start = get_wall_time();

    uint64_t sum = 0;

    uint32_t nk0 = 0x12345678;
    uint32_t nk1 = 0x23456789;
    uint32_t nk2 = 0x34567890;
    uint32_t nk3 = 0x45678901;

    __m128i mask = _mm_set1_epi32(0xff);

    uint64_t i;
    for(i = 0; i < 100000000; i++)
    {
        uint32_t newKeys[] = {nk0, nk1, nk2, nk3};

        __m128i *nk_sse = (__m128i*)(&newKeys);

        __m128i opa = _mm_and_si128(*nk_sse, mask);
        __m128i opr8 = _mm_srai_epi32 (*nk_sse, 8);
        __m128i opr16 = _mm_srai_epi32 (*nk_sse, 16);
        __m128i opr24 = _mm_srai_epi32 (*nk_sse, 24);

        __m128i oprsum = _mm_add_epi32(_mm_add_epi32(_mm_add_epi32(opa, _mm_and_si128(opr8, mask)), _mm_and_si128(opr16, mask)), _mm_and_si128(opr24, mask));

        uint32_t* oprsum_ptr = (uint32_t*)(&oprsum);

        uint32_t sum_sse = oprsum_ptr[0] + oprsum_ptr[1] + oprsum_ptr[2] + oprsum_ptr[3];
        sum += sum_sse;

        nk0--;
        nk1--;
        nk2--;
        nk3--;
    }

    double end = get_wall_time();

    double ms = end - start;

    printf("SSE Test - Sum: %lu, ms: %f\n", sum, ms);
}

static void test()
{
    double start = get_wall_time();

    uint64_t sum = 0;

    uint32_t nk0 = 0x12345678;
    uint32_t nk1 = 0x23456789;
    uint32_t nk2 = 0x34567890;
    uint32_t nk3 = 0x45678901;

    uint64_t i;
    for(i = 0; i < 100000000; i++)
    {
        uint8_t res0 = (uint8_t) (nk0 & 0xff);
        uint8_t res1 = (uint8_t) (nk0 >> 8);
        uint8_t res2 = (uint8_t) (nk0 >> 16);
        uint8_t res3 = (uint8_t) (nk0 >> 24);

        uint8_t res4 = (uint8_t) (nk1 & 0xff);
        uint8_t res5 = (uint8_t) (nk1 >> 8);
        uint8_t res6 = (uint8_t) (nk1 >> 16);
        uint8_t res7 = (uint8_t) (nk1 >> 24);

        uint8_t res8 = (uint8_t) (nk2 & 0xff);
        uint8_t res9 = (uint8_t) (nk2 >> 8);
        uint8_t res10 = (uint8_t) (nk2 >> 16);
        uint8_t res11 = (uint8_t) (nk2 >> 24);

        uint8_t res12 = (uint8_t) (nk3 & 0xff);
        uint8_t res13 = (uint8_t) (nk3 >> 8);
        uint8_t res14 = (uint8_t) (nk3 >> 16);
        uint8_t res15 = (uint8_t) (nk3 >> 24);

        sum += res0 + res1+ res2 + res3 + res4 + res5 + res6 + res7 + res8 + res9
        + res10 + res11 + res12 + res13 + res14  + res15;

        nk0--;
        nk1--;
        nk2--;
        nk3--;
    }

    double end = get_wall_time();

    double ms = end - start;

    printf("Normal Test - Sum: %lu, ms: %f\n", sum, ms);
}

int main (int argc, char **argv)
{
    test();
    test_sse();
    return 0;
}

您使用了错误的工具来衡量绩效。时钟,至少在符合标准的平台上,为您提供CPU时间,而不是挂钟时间

另一件您做错的事情是打印带有%d的uint64\t。当int小于64位时,这具有未定义的行为。此时您的int打印可能只是接收垃圾

编辑:现在您已经修复了代码,我已经将其编译为汇编器gcc选项-S。事实上,gcc在向量化和展开测试函数方面做得非常好。使用我的三个编译器,我得到了完全不同的结果,都是用-O3-march=native编译的

国际商会:

通用条款4.6:

Normal Test - Sum: 169248636030, ms: 0.462793
SSE Test - Sum: 169248636030, ms: 0.348453
叮当声:

Normal Test - Sum: 169248636030, ms: 0.625905
SSE Test - Sum: 169248636030, ms: 0.423343
所以icc和clang在未优化的代码上做的差不多,但是gcc做得更好。使用gcc和clang,您的sse代码更好,而icc则更宽松。总的来说,icc是一个商业编译器,你必须为它支付真正的费用,与公共领域的免费编译器相比,它的性能确实令人失望

编辑2:

现在有了新版本的gcc,我甚至可以

gcc 4.7:

Normal Test - Sum: 169248636030, ms: 0.158695
SSE Test - Sum: 169248636030, ms: 0.406921
所以你可以看到,正常测试的效果更进一步,而
SSE测试比以前差了一点。

您使用了错误的工具来衡量性能。时钟,至少在符合标准的平台上,为您提供CPU时间,而不是挂钟时间

另一件您做错的事情是打印带有%d的uint64\t。当int小于64位时,这具有未定义的行为。此时您的int打印可能只是接收垃圾

编辑:现在您已经修复了代码,我已经将其编译为汇编器gcc选项-S。事实上,gcc在向量化和展开测试函数方面做得非常好。使用我的三个编译器,我得到了完全不同的结果,都是用-O3-march=native编译的

国际商会:

通用条款4.6:

Normal Test - Sum: 169248636030, ms: 0.462793
SSE Test - Sum: 169248636030, ms: 0.348453
叮当声:

Normal Test - Sum: 169248636030, ms: 0.625905
SSE Test - Sum: 169248636030, ms: 0.423343
所以icc和clang在未优化的代码上做的差不多,但是gcc做得更好。使用gcc和clang,您的sse代码更好,而icc则更宽松。总的来说,icc是一个商业编译器,你必须为它支付真正的费用,与公共领域的免费编译器相比,它的性能确实令人失望

编辑2:

现在有了新版本的gcc,我甚至可以

gcc 4.7:

Normal Test - Sum: 169248636030, ms: 0.158695
SSE Test - Sum: 169248636030, ms: 0.406921
所以你可以看到,正常测试的效果更进一步,而
SSE测试比以前差了一点。

为什么要用-Os编译?我的错,我本来打算用-O3编译的。以下是-O3:-正常-2,SSE-6@Partho顺便说一句,你看过非see测试的反汇编吗?当给出-msse4时,编译器本身可能也会使用SSE指令,至少GCC承诺了类似的东西。为什么用-Os编译?我的错,我想用-O3来编译。以下是-O3:-正常-2,SSE-6@Partho顺便说一句,你看过非see测试的反汇编吗?当给出-msse4时,编译器本身可能也会使用SSE指令,至少GCC承诺了类似的内容。感谢您提供的信息。我用的是墙上的时钟时间解决方案。还修复了printf格式。谢谢你提供的信息。我用的是墙上的时钟时间解决方案。还修复了printf格式。