2

メモリのチャンクにゼロを割り当てる必要がある場合。アーキテクチャが32ビットの場合、long long(特定のアーキテクチャでは8バイト)の割り当ては(4バイト)の割り当てよりも効率的intですか、それとも2つのint割り当てに等しくなりますか?また、を使用する場合は4倍のループが必要になるため、同じメモリチャンクを使用するint場合よりも効率的に割り当てられます。charcharint

4

5 に答える 5

7

なぜ使用しないのmemset()ですか?

http://www.elook.org/programming/c/memset.html

(上記サイトより)

構文:

#include <string.h>
void *memset( void *buffer, int ch, size_t count ); 

説明:

関数 memset() は、ch を buffer の最初の count 文字にコピーし、buffer を返します。memset() は、メモリのセクションをある値に初期化するのに役立ちます。たとえば、次のコマンドを実行します。

memset( the_array, '\0', sizeof(the_array) ); 

the_array のすべての値をゼロに設定する非常に効率的な方法です。

于 2012-08-20T23:44:17.210 に答える
2

コンパイラがスマート/最適化されている場合、あなたの質問に対する答えは「はい」と「はい」です。

SSE を備えたマシンでは 128 ビットのチャンクで作業できるという興味深い点:) それでも、これは単なる私の意見です。簡潔さとバランスの取れた読みやすさを常に強調するようにしてくださいmemset。最速ではないかもしれませんが、コードを管理している人に「この配列を初期化または設定しています」と伝えます

とにかくここにいくつかのテストコードがあります。修正が必要な場合はお知らせください。

#include <time.h>
#include <xmmintrin.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define NUMBER_OF_VALUES 33554432

int main()
{
    int *values;
    int result = posix_memalign((void *)&values, 16, NUMBER_OF_VALUES * sizeof(int));
    if (result)
    {
        printf("Failed to mem allocate \n");
        exit(-1);
    }
    clock_t start, end;

    int *temp = values, total = NUMBER_OF_VALUES; 
    while (total--)
        *temp++ = 0;

    start = clock();
    memset(values, 0, sizeof(int) * NUMBER_OF_VALUES);
    end = clock();

    printf("memset time %f\n", ((double) (end - start)) / CLOCKS_PER_SEC);

    start = clock();
    {
        int index = 0, total = NUMBER_OF_VALUES * sizeof(int);
        char *temp = (char *)values;
        for(; index < total; index++)
            temp[index] = 0;
    }
    end = clock();

    printf("char-wise for-loop array indices time %f\n", ((double) (end - start)) / CLOCKS_PER_SEC);

    start = clock();
    {
        int index = 0, *temp = values, total = NUMBER_OF_VALUES;
        for (; index < total; index++)
            temp[index] = 0;
    }
    end = clock();

    printf("int-wise for-loop array indices time %f\n", ((double) (end - start)) / CLOCKS_PER_SEC);

    start = clock();
    {
        int index = 0, total = NUMBER_OF_VALUES/2;
        long long int *temp = (long long int *)values;
        for (; index < total; index++)
            temp[index] = 0;
    }
    end = clock();

    printf("long-long-int-wise for-loop array indices time %f\n", ((double) (end - start)) / CLOCKS_PER_SEC);

    start = clock();
    {
       int index = 0, total = NUMBER_OF_VALUES/4;
       __m128i zero = _mm_setzero_si128();
       __m128i *temp = (__m128i *)values;
       for (; index < total; index++)
           temp[index] = zero; 
    }
    end = clock();

    printf("SSE-wise for-loop array indices time %f\n", ((double) (end - start)) / CLOCKS_PER_SEC);

    start = clock();
    {
        char *temp = (char *)values;
        int total  = NUMBER_OF_VALUES * sizeof(int);
        while (total--)
            *temp++ = 0;        
    }
    end = clock();

    printf("char-wise while-loop pointer arithmetic time %f\n", ((double) (end - start)) / CLOCKS_PER_SEC);

    start = clock();
    {
        int *temp = values, total = NUMBER_OF_VALUES;
        while (total--)
            *temp++ = 0;
    }
    end = clock();

    printf("int-wise while-loop pointer arithmetic time %f\n", ((double) (end - start)) / CLOCKS_PER_SEC);

    start = clock();
    {
        long long int *temp = (long long int *)values;
        int total = NUMBER_OF_VALUES/2;
        while (total--)
            *temp++ = 0;
    }
    end = clock();

    printf("long-ling-int-wise while-loop pointer arithmetic time %f\n", ((double) (end - start)) / CLOCKS_PER_SEC);

    start = clock();
    {
        __m128i zero = _mm_setzero_si128();
        __m128i *temp = (__m128i *)values;
        int total = NUMBER_OF_VALUES/4;
        while (total--)
            *temp++ = zero;
    }
    end = clock();

    printf("SSE-wise while-loop pointer arithmetic time %f\n", ((double) (end - start)) / CLOCKS_PER_SEC);


    free(values);
    return 0;
}

ここにいくつかのテストがあります:

$ gcc time.c
$ ./a.out 
memset time 0.025350
char-wise for-loop array indices time 0.334508
int-wise for-loop array indices time 0.089259
long-long-int-wise for-loop array indices time 0.046997
SSE-wise for-loop array indices time 0.028812
char-wise while-loop pointer arithmetic time 0.271187
int-wise while-loop pointer arithmetic time 0.072802
long-ling-int-wise while-loop pointer arithmetic time 0.039587
SSE-wise while-loop pointer arithmetic time 0.030788

$ gcc -O2 -Wall time.c
MacBookPro:~ samyvilar$ ./a.out 
memset time 0.025129
char-wise for-loop array indices time 0.084930
int-wise for-loop array indices time 0.025263
long-long-int-wise for-loop array indices time 0.028245
SSE-wise for-loop array indices time 0.025909
char-wise while-loop pointer arithmetic time 0.084485
int-wise while-loop pointer arithmetic time 0.025277
long-ling-int-wise while-loop pointer arithmetic time 0.028187
SSE-wise while-loop pointer arithmetic time 0.025823

私の情報:

$ gcc --version
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ uname -a
Darwin MacBookPro 10.8.0 Darwin Kernel Version 10.8.0: Tue Jun  7 16:33:36 PDT 2011; root:xnu-1504.15.3~1/RELEASE_I386 i386

memsetおそらくインラインアセンブリを使用してかなり最適化されていますが、これもコンパイラによって異なります...

いくつかのタイミングが収束し始めると、 gcc は非常に積極的に最適化している-O2ようです。アセンブリを確認する必要があると思います。

あなたが好奇心旺盛な場合は、電話するだけgcc -S -msse2 -O2 -Wall time.cで、アセンブリは次の場所にありますtime.s

于 2012-08-21T05:15:11.890 に答える
0

高レベルのプログラミング言語での追加の反復は常に避けてください。バイトをループするのではなく、int を 1 回反復するだけで、コードはより効率的になります。

于 2012-08-20T23:45:10.867 に答える
0

割り当ての最適化はほとんどのアーキテクチャで行われるため、32 ビット x86 では 4 バイトのワード サイズに合わせられます。したがって、同じサイズのメモリを割り当てることは問題ではありません (1MB 相当の long の memset と 1MB 相当の char 型に違いはありません)。

于 2012-08-20T23:45:20.240 に答える
0

1. long long(8 bytes) vs two int(4 bytes)- 長く続けたほうがいいです。4 バイト要素を 2 つ割り当てるよりも、8 バイト要素を 1 つ割り当てた方がパフォーマンスが向上するためです。

2. int (4 bytes) vs four char(1 bytes)- ここでは int を使用することをお勧めします。

要素を 1 つだけ宣言している場合は、以下のようにゼロを直接割り当てることができます。

long long a;
int b;
....
a = 0; b = 0;

ただし、要素の配列を宣言している場合は、以下のような関数nに進みます。memeset

long long a[10];
int b[20];
....
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));

宣言自体で初期化したい場合は、必要はありませんmemset

long long a = 0;
int b = 0;

また

long long a[10] = {0};
int b[20] = {0};
于 2012-08-21T03:11:19.017 に答える