zugriff auf struktur oder array, was ist schneller?

Gast #7091762
Lesenswert?

Einen schönen guten morgen,

ich habe mal eine interessensfrage.

Auf was wird schneller zugegriffen, struktur oder array, oder macht der 
compiler eh das selbe daraus?
1
typedf struct
2
{
3
  uint32 a;
4
  uint32 b;
5
  uint32 c;
6
  uint32 d;
7
}testStruct_ts
8

9
testStruct_ts testStruct_s;
10

11
uint32 testArray[4];
1
x = testStruct_s.a;
2
y = testArray[0];
#7091772
Lesenswert?

Also, wenn mich die Frage interessieren würde, dann würde ich es 
herausfinden.
Konkret in deinem Beispiel habe ich eine Vermutung. Um die zu belegen 
müsste man es kompilieren und im Code nachsehen. Kannst du aber bei 
Interesse wahrscheinlich auch selber. Nur du weißt, von welcher Umgebung 
du redest...
#7091776
Lesenswert?

Felix schrieb:
> Auf was wird schneller zugegriffen, struktur oder array, oder macht der
> compiler eh das selbe daraus?

Solange du gleiche Datentypen innerhalb deines Array/Struct hast wird 
das immer auf eine Base Adresse+Offset rauslaufen. Sollte also gleich 
sein.
Bei einem Array ist der gleiche Datentypen ja gesetzt. Bei einer Struct 
könntest du natürlich auch Datentypen mischen. Dann wird eine Struct mit 
Sicherheit höhere Kosten bzgl Laufzeit bedeuten. Gerade wenn die 
Plattform evtl. nur wenig spezielle Zugriffsbefehle unterstützt.
Persönliche Seite #7091796
Lesenswert?

N. M. schrieb:
> Dann wird eine Struct mit
> Sicherheit höhere Kosten bzgl Laufzeit bedeuten.

Eher ist der Array-Zugriff langsamer, wenn der Index nicht zur 
Compile-Time bekannt ist, weil dann je nach Plattform (z.B. beim AVR) 
erst Basis+Offset berechnet werden muss. Leistungsfähigere Prozessoren 
(z.B. ARM) können das (meistens) direkt im Ladebefehl machen.
Gast #7091814
Lesenswert?

Felix schrieb:
> ich habe mal eine interessensfrage.
>
> Auf was wird schneller zugegriffen, struktur oder array, oder macht der
> compiler eh das selbe daraus?

Der Compiler macht meist das Gleiche draus.

Für die Geschwindigkeit dürfte das aber nicht entscheidend sein,
da die meisten Prozessoren heute parallel arbeiten, und den 
Assembler-Code
sowieso umstellen.

Interessanter wird es, wenn du ein Feld von Strukturen hast:
da ist der Offset nicht konstant.

Kleiner Test unter Windows 10 x64:
1
typedef struct
2
  2 {
3
  3   unsigned a;
4
  4   unsigned b;
5
  5   unsigned c;
6
  6   unsigned d;
7
  7 } TS;
8
  8
9
  9
10
 10 int foo1(TS ar[], unsigned index)
11
 11 {
12
 12     return ar[index].d;
13
 13 }
14
 14
15
 15
16
 16 unsigned foo2(unsigned ar[], unsigned index)
17
 17 {
18
 18     return ar[index * sizeof(TS)/sizeof(unsigned) + 3];
19
 19 }
20
 20
1
Ein alter 2008 cl macht draus:
2

3
cl -O1 -c test.c
4
dumpbin -disasm test.obj
5

6
Note: Das erste Argument (ar) ist im Register ecx,
7
      edx ist das zweite Argument (index).
8

9
foo1:
10
  0000000000000000: 8B C2              mov         eax,edx
11
  0000000000000002: 48 03 C0           add         rax,rax
12
  0000000000000005: 8B 44 C1 0C        mov         eax,dword ptr [rcx+rax*8+0Ch]
13
  0000000000000009: C3                 ret
14

15
foo2:
16
  0000000000000000: 8B C2              mov         eax,edx
17
  0000000000000002: 48 C1 E0 04        shl         rax,4
18
  0000000000000006: 48 C1 E8 02        shr         rax,2
19
  000000000000000A: 8B 44 81 0C        mov         eax,dword ptr [rcx+rax*4+0Ch]
20
  000000000000000E: C3                 ret
21

22
Der Compiler macht also nicht das Gleiche, sondern genau das, was im test.c steht.  Er multipliziert index mit 16 (shl rax,4) und dividiert dann durch
23
4 (shr rax,2)
24

25
Schreibe ich "ar[index * ( sizeof(TS)/sizeof(unsigned) ) + 3];"
26
ist der Assembler Code von foo1 und foo2 identisch, da hier der Klammerausdruck als erstes ausgewertet wird und eine Konstante erkannt wird.

Ein 2022 cl liefert in beiden Fällen das Gleiche.
Genauso ein neuer clang.

gcc unter mingw macht irgendein komisches Padding dazu:
1
foo1:
2
  0000000000000000: 89 D2              mov         edx,edx
3
  0000000000000002: 48 C1 E2 04        shl         rdx,4
4
  0000000000000006: 8B 44 0A 0C        mov         eax,dword ptr [rdx+rcx+0Ch]
5
  000000000000000A: C3                 ret
6
foo2:
7
  000000000000000B: 89 D2              mov         edx,edx
8
  000000000000000D: 48 C1 E2 04        shl         rdx,4
9
  0000000000000011: 8B 44 0A 0C        mov         eax,dword ptr [rdx+rcx+0Ch]
10
  0000000000000015: C3                 ret
11
  0000000000000016: 90                 nop
12
  0000000000000017: 90                 nop
13
  0000000000000018: 90                 nop
14
  0000000000000019: 90                 nop
15
  000000000000001A: 90                 nop
16
  000000000000001B: 90                 nop
17
  000000000000001C: 90                 nop
18
  000000000000001D: 90                 nop
19
  000000000000001E: 90                 nop
20
  000000000000001F: 90                 nop
#7091897
Lesenswert?

🐧 DPA 🐧 schrieb:
> Nö, ist immernoch ein konstanter Offset, der zur compile time bekannt
> ist.

Ich meinte das bezogen auf das Alignement. Je nach dem gibt es da ja 
sehr ungünstige Konstellationen.

Niklas G. schrieb:
> Eher ist der Array-Zugriff langsamer, wenn der Index nicht zur
> Compile-Time bekannt ist

Ja klar. Wenn man
testStruct_s.a;
und
testArray[i];
vergleicht muss natürlich beim Array der Offset zur Laufzeit berechnet 
werden. Der dynamische Zugriff fehlt ja beim struct. Von dem her ist der 
Vergleich etwas unfair.
Man könnte natürlich noch eine Union um die Struct/Array legen. Dann 
hätte man beide Möglichkeiten.
Gast #7091956
Lesenswert?

Evwntuell wären noch vor und nachteile von Arrays nach Komponente vs. 
nach Objelt interessant:
1
struct sa {
2
  int* a;
3
  bool* b;
4
};
5

6
struct as {
7
  int a;
8
  bool b;
9
};
10

11
struct as xas[5];
12

13
struct sa xsa = {
14
  .a = (int[5]){0},
15
  .b = (bool[5]){0},
16
};
17

18
// xsa.a[i] vs. xas[i].a
#7092043
Lesenswert?

beo bachta schrieb:
> Kommt es denn nicht drauf an auf welcher Architektur das
> Ganze laufen soll?

Da die Frage im Unterforum "PC-Programmierung" gepostet wurde kann man 
erst mal von einem PC ausgehen.
Und das macht die Frage eigentlich fast obsolet, denn moderne PCs haben 
soviel Rechenleistung dass sich solche Fragen zur Optimierung praktisch 
nie lohnen.
Viel eher lohnen sich dann Überlegungen zur Softwarearchitektur, den 
verwendeten Algorithmen oder unterschiedlichen Speicherstrategien wie 
z.B. (sortierten) Listen, Bäume, Maps usw.
Zumal Arrays und Strukturen eigentlich grundverschiedene Strukturen sind 
die beide ganz unterschiedliche Anwendungsszenarien haben.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren