Forum: PC-Programmierung zugriff auf struktur oder array, was ist schneller?


von Felix (Gast)


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];

von Lars Hempel (Gast)


Lesenswert?

Hallo,

teste es doch mit dem Compiler Explorer. https://godbolt.org/

Glaube nicht das es gleich ist.

von 🐧 DPA 🐧 (Gast)


Lesenswert?

Macht in dem Fall genau das selbe draus: https://godbolt.org/z/qvExMK4eK

von Klaus W. (mfgkw)


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...

von N. M. (mani)


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.

von 🐧 DPA 🐧 (Gast)


Lesenswert?

N. M. schrieb:
> Bei einer Struct
> könntest du natürlich auch Datentypen mischen. Dann wird eine Struct mit
> Sicherheit höhere Kosten bzgl Laufzeit bedeuten.

Nö, ist immernoch ein konstanter Offset, der zur compile time bekannt 
ist.

von Udo S. (urschmitt)


Lesenswert?

Der "use case" einer Struktur ist doch recht verschieden von dem eines 
Arrays.
Was willst du erreichen, welches Problem lösen?

von Niklas G. (erlkoenig) Benutzerseite


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.

von udok (Gast)


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

von N. M. (mani)


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.

von DPA (Gast)


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

von beo bachta (Gast)


Lesenswert?

Lars Hempel schrieb:
> teste es doch mit dem Compiler Explorer

Kommt es denn nicht drauf an auf welcher Architektur das
Ganze laufen soll? Vielleicht solte der TO das noch angeben.

von äpfel und birnen (Gast)


Lesenswert?

Felix schrieb:
> Auf was wird schneller zugegriffen, struktur oder array

Als ein lokale Variable oder als Parameter einer Funktion? Übergabe an 
die Funktion per Pointer auch bei der Struktur?

Das sind Äpfel undn Birnen.

von Lars Hempel (Gast)


Lesenswert?

beo bachta schrieb:
>> teste es doch mit dem Compiler Explorer
>
> Kommt es denn nicht drauf an auf welcher Architektur das
> Ganze laufen soll? Vielleicht solte der TO das noch angeben.
>
Sicher, aber eine Architektur erwähnte der TO nicht

von Udo S. (urschmitt)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.