[C++] *w++ = *w++ = 0: bug?

Pagina: 1
Acties:

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Het gaat om de volgende code. Ik dacht dat a[0] en a[1] beide 0 zouden zijn, maar alleen a[0] is 0.
C++:
1
2
3
char a[2] = {1, 1};
char* w = a;
*w++ = (*w++ = 0);

De post-increment operator wordt dus blijkbaar pas uitgevoerd na de volledige expressie.
Mijn vraag is nu, waarom?
Ik dacht dat de hele expressie (inclusief post-increment) tussen haakjes zou worden uitgevoerd voordat de tweede assignment wordt uitgevoerd.

  • Daedalus
  • Registratie: Mei 2002
  • Niet online

Daedalus

Moderator Apple Talk

Keep tryin'

Dat is nu het vervelende van dit soort operatoren, de implementatie hang af per compiler. Er is geloof ik wel een standaard, maar niet elke compiler houd zich daaraan. Zowieso ben ik niet zo'n fan van dit soort code, mede om bovenstaande rede. Je weet nooit precies wat de code doet.

“You know what I've noticed Hobbes? Things don't bug you if you don't think about them. So from now on, I simply won't think about anything I don't like, and I'll be happy all the time!” | 宇多田ヒカル \o/


Verwijderd

Heeft volgens mij te maken met voorrangsregels, postincrement heeft een hogere prioriteit dan assignment en is links naar rechts associatief.

edit:
mcDaedalus: is dat niet alleen het geval wanneer operators met dezelfde prioriteit worden gebruikt?
zoiets als a=b+c+d+f dat je dan niet weet wat hij eerst zal doen.

[ Voor 40% gewijzigd door Verwijderd op 05-03-2004 15:43 ]


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 23:30

NMe

Quia Ego Sic Dico.

Ik vraag me af wat je probeert te doen... Je doet nogal vage dingen naar mijn mening. Je bent met het volgende toch ook klaar?
C++:
1
2
char a[2] = {1, 1};
char* w = (a[1] = 0);

Plus dat het enige dat je bereikt is dat je 2 pointers hebt naar hetzelfde adres, dus als je de ene verandert, verandert de andere ook... Uitkijken dus.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22-05 16:53
NMe84 schreef op 05 maart 2004 @ 15:43:
Ik vraag me af wat je probeert te doen... Je doet nogal vage dingen naar mijn mening. Je bent met het volgende toch ook klaar?
C++:
1
char* w = (a[1] = 0);
Heb het idee dat dat niet helemaal gaat werken.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Verwijderd

NMe84 schreef op 05 maart 2004 @ 15:43:
Je bent met het volgende toch ook klaar?
Als je het goed wil doen, doe het dan ook meteen helemaal goed:
C++:
1
2
char a[2] = {0, 0};
char* w = &a[2];
;)
Maar ik denk dat het om iets meer code gaat dan wat hier afgebeeld is, maar de manier van de TS is natuurlijk nooit goed...

Waarom niet gewoon deze code, is toch ook precies goed:
C++:
1
2
*w++ = 0;
*w++ = 0;

Al je operaties op een regel gooien gaat echt geen betere code genereren, compilers zijn slim genoeg hoor... Een beetje compiler zal "w" initialiseren op &a[2] (of helemaal wegoptimaliseren afhankelijk van de situatie) en zal mogelijk zelfs naar a[0] ... a[1] in een keer 16 bits-breed "0" wegschrijven...

[ Voor 6% gewijzigd door Verwijderd op 05-03-2004 15:56 ]


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Het aangegeven gedrag is undefined en compiler-dependent, en soms zelfs afhankelijk van of je een debug- of releasebuild hebt.

Stroustrup's advies: gebruik nooit dezelfde variable 2 keer binnen 1 statement als lvalue. Punt.
De post-increment operator wordt dus blijkbaar pas uitgevoerd na de volledige expressie.
Omdat het de POST-increment operator is ;)

[ Voor 26% gewijzigd door curry684 op 05-03-2004 16:01 ]

Professionele website nodig?


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 23:30

NMe

Quia Ego Sic Dico.

Verwijderd schreef op 05 maart 2004 @ 15:55:
Als je het goed wil doen, doe het dan ook meteen helemaal goed:
C++:
1
2
char a[2] = {0, 0};
char* w = &a[2];
;)
Mjah, ik dacht inderdaad al dat ik wat fout had, ben nooit zo'n ster geweest met pointers en heb alweer een tijdje niet geoefend. ;)
Verwijderd schreef op 05 maart 2004 @ 15:55:
Al je operaties op een regel gooien gaat echt geen betere code genereren, compilers zijn slim genoeg hoor... Een beetje compiler zal "w" initialiseren op &a[2] (of helemaal wegoptimaliseren afhankelijk van de situatie) en zal mogelijk zelfs naar a[0] ... a[1] in een keer 16 bits-breed "0" wegschrijven...
Buiten het feit dat je compiler misschien gekke dingen gaat doen is er een minstens net zo belangrijke reden om niet zo te stunten. Leesbaarheid. Je kan de meest prachtige code hebben geschreven, op zo'n manier dat het allemaal in één expressie past, maar als je 2 dagen later geen klote meer snapt van je eigen code heb je er nog nix aan...

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Verwijderd

Ok, ik zal niet inhoudelijk reageren op je code (dat hebben al genoeg mensen gedaan; ik neem aan dat dit gewoon een testje van jou is, geen serieuze code).

De ++ postfix operator wordt pas uitgevoerd na het statement in kwestie. Je expressie tussen de haken is wel afgelopen, maar het statement nog niet; er moet nog een assignment gebeuren.
Als je het van links naar rechts zou evalueren zou je kunnen zeggen dat de ++ operatoren pas worden uitgevoerd als je bij de ';' bent aangekomen.
Dus ik geloof niet dat dit per compiler verschilt...

Enne... de compiler heeft altijd het laatste woord :-)

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Verwijderd schreef op 05 maart 2004 @ 16:10:
Ok, ik zal niet inhoudelijk reageren op je code (dat hebben al genoeg mensen gedaan; ik neem aan dat dit gewoon een testje van jou is, geen serieuze code).
Het was wel serieuze code en wel om een gzip header te genereren:
C++:
1
2
3
4
5
6
7
8
Cvirtual_binary d;
unsigned long cb_d = cb_s + (cb_s + 999) / 1000 + 12;
byte* w = d.write_start(10 + cb_d + 8);
*w++ = 0x1f;
*w++ = 0x8b;
*w++ = Z_DEFLATED;
*w++ = *w++ = *w++ = *w++ = *w++ = *w++ = 0;
*w++ = 3;

Ik wilde zes keer een nul-byte wegschrijven, maar door mijn verkeerde aanname over evaluatie-volgorde werd er maar een nul-byte weggeschreven.
Pas na maanden/jaren kom ik hier toevallig achter en ik zal er eens wat aan doen.

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

curry684 schreef op 05 maart 2004 @ 16:00:
Stroustrup's advies: gebruik nooit dezelfde variable 2 keer binnen 1 statement als lvalue. Punt.
Standaard zegt hierover dit:
4 Except where noted, the order of evaluation of operands of individual
operators and subexpressions of individual expressions, and the order
in which side effects take place, is unspecified. Between the previ-
ous and next sequence point a scalar object shall have its stored
value modified at most once by the evaluation of an expression. Fur-
thermore, the prior value shall be accessed only to determine the
value to be stored. The requirements of this paragraph shall be met
for each allowable ordering of the subexpressions of a full expres-
sion; otherwise the behavior is undefined. [Example:
code:
1
2
3
4
5
          i = v[i++];      // the behavior is undefined
          i = 7, i++, i++; // `i' becomes 9

          i = ++i + 1;     // the behavior is undefined
          i = i + 1;       // the value of 'i' is incremented
--end example]

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Wat zijn sequence points dan?

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Sequence points zijn bepaalde punten in je code flow. Alles wat volgens je code daarvoor gebeurt heeft waarneembare effecten ervoor; alles wat daarna komt heeft alleen maar merkbare effecten daarna. Interne details zoals CPU caches tellen daarbij niet mee, I/O wel en memory writes is typisch compiler-afhankelijk (ivm shared memory e.d.)

Sequence points vinden we voor function calls en returns, bij de ; op het eind van een statement en dergelijke. Ze zijn dus niet altijd georderd:
code:
1
2
3
4
void foo( int, int );
int g();
int h();
foo( g(), h() );

Er is een sequence point voor de aanroep van g() en h(), maar omdat de volgorde van argument evaluatie ongespecificieerd is, is de volgorde van sequence points dat dus ook.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • mOrPhie
  • Registratie: September 2000
  • Laatst online: 23:33

mOrPhie

❤️❤️❤️❤️🤍

OlafvdSpek schreef op 05 maart 2004 @ 20:19:

Ik wilde zes keer een nul-byte wegschrijven
Waarom zou je zoiets niet met memset doen?

Een experimentele community-site: https://technobabblenerdtalk.nl/. DM voor invite code.


Verwijderd

Verwijderd schreef op 05 maart 2004 @ 15:55:
[...]

Als je het goed wil doen, doe het dan ook meteen helemaal goed:
C++:
1
2
char a[2] = {0, 0};
char* w = &a[2];
;)
Wat is hier de bedoeling van? Zou het dit niet moeten zijn:

C++:
1
2
char a[2] = {0, 0};
char* w = a;
?


Naast memset zou je ook een simpel for-loopje kunnen gebruiken:

C:
1
 for(int i = 0; i < 6; *w++ = 0, i++);

[ Voor 4% gewijzigd door Verwijderd op 06-03-2004 09:54 ]


  • mOrPhie
  • Registratie: September 2000
  • Laatst online: 23:33

mOrPhie

❤️❤️❤️❤️🤍

Verwijderd schreef op 06 maart 2004 @ 09:53:
[...]
C++:
1
2
char a[2] = {0, 0};
char* w = a;
?
Neej, dan heb je namelijk a[0] te pakken.

Een experimentele community-site: https://technobabblenerdtalk.nl/. DM voor invite code.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Voor snelheid moet je proberen de bytes te packen in een type van de adreserings grootte, meestal uint32. Bij het schrijven/lezen van bytes heb je namelijk trage memory accesses, die toch al het hele woord gebruiken. Alleen als je dat doet moet je ontzettend uitkijken dat je geen allignment errors veroorzaakt. Op een PC is het niet echt een punt, maar verlies je wel je snelheids winst als alles unalligned is. Maar bv op een sparc is het crash&burn...

Verwijderd

Zoijar schreef op 06 maart 2004 @ 12:13:
Voor snelheid moet je proberen de bytes te packen in een type van de adreserings grootte, meestal uint32. Bij het schrijven/lezen van bytes heb je namelijk trage memory accesses, die toch al het hele woord gebruiken. Alleen als je dat doet moet je ontzettend uitkijken dat je geen allignment errors veroorzaakt. Op een PC is het niet echt een punt, maar verlies je wel je snelheids winst als alles unalligned is. Maar bv op een sparc is het crash&burn...
Dat kan wel zo zijn maar ik denk niet dat dat hier echt van toepassing is. Het gaat maar om een paar bytes in een header. Dan kun je het beter netjes oplossen dan alles zwaar gaan lopen te optimaliseren.
mOrPhie schreef op 06 maart 2004 @ 10:13:
[...]


Neej, dan heb je namelijk a[0] te pakken.
Mja, ok. Maar dan nog is &a[2] niet helemaal frisjes, aangezien a[2] niet bestaat.

[ Voor 62% gewijzigd door Verwijderd op 06-03-2004 12:56 ]


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Verwijderd schreef op 05 maart 2004 @ 15:55:
C++:
1
2
char a[2] = {0, 0};
char* w = &a[2];
Waarom &a[2] in plaats van a + 2?

En memset is inderdaad een prima optie, ik heb geen idee waarom ik daar toen niet aan gedacht heb.

  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Zoijar schreef op 06 maart 2004 @ 12:13:
Voor snelheid moet je proberen de bytes te packen in een type van de adreserings grootte, meestal uint32. Bij het schrijven/lezen van bytes heb je namelijk trage memory accesses, die toch al het hele woord gebruiken. Alleen als je dat doet moet je ontzettend uitkijken dat je geen allignment errors veroorzaakt. Op een PC is het niet echt een punt, maar verlies je wel je snelheids winst als alles unalligned is. Maar bv op een sparc is het crash&burn...
Met VC++ kun je dan net zo goed memcpy of memset gebruiken, die worden voor kleine lengtes toch direct in dat soort code omgezet. Bijvoorbeeld:
C++:
1
2
char *w = new char[6];
memset(w, 0, 6);

wordt:
GAS:
1
2
3
4
5
6
push 6                |
                      | xor     esi, esi             ; esi = 0
call 'operator new[]' |
                      | mov     dword ptr [eax], esi ; 4x 0
add  esp, 4           |
                      | mov     word ptr [eax+4], si ; 2x 0

(Ik heb het in 2en gesplistst omdat de compiler de 2 coderegels als optimalisatie door elkaar geweven heeft).

edit:
C++:
1
2
3
4
5
6
7
const unsigned char GZIP_HEADER_VALS[] = 
    { 0x1F, 0x8B, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 }; 

...

unsigned char *w = new unsigned char[10];
memcpy(w, GZIP_HEADER_VALS, sizeof(GZIP_HEADER_VALS));

wordt:
GAS:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CONST   segment
 _GZIP_HEADER_VALS  db 1Fh, 8Bh, 08h, 00h, 00h
                    db 00h, 00h, 00h, 00h, 03h
CONST   ends

...

push    10
call    'operator new[]'

mov     ecx, dword ptr [_GZIP_HEADER_VALS]
mov     dword ptr [eax], ecx
mov     edx, dword ptr [_GZIP_HEADER_VALS+4]
mov     dword ptr [eax+4], edx
mov     cx,  word ptr  [_GZIP_HEADER_VALS+8]
mov     word ptr  [eax+8], cx

Het kopieren wordt dus gedaan met 2x een dword (32-bits) en 1x een word (16-bits).

[ Voor 27% gewijzigd door madwizard op 06-03-2004 13:35 ]

www.madwizard.org


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Welke versie van VC is dat?
Perfect is de code niet, want met drie movs ben je in principe klaar en heb je GZIP_HEADER_VALS helemaal niet nodig.

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Ah ok, ja dat ziet er wel goed uit :)

Alleen dit?
GAS:
1
2
mov     ecx, dword ptr [_GZIP_HEADER_VALS]
mov     dword ptr [eax], ecx

Read-after-write? Of veroorzaakt dat tegenwoordig geen stall meer? Ben er een beetje uit, het assembler gebeuren...laatste dat ik ken is pentium (1).

(bestaat STOSTW, store-string-word, nog, of is dat traag?)

[ Voor 11% gewijzigd door Zoijar op 06-03-2004 13:57 . Reden: quote en code door elkaar ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22-05 16:53
Verwijderd schreef op 06 maart 2004 @ 12:54:
Mja, ok. Maar dan nog is &a[2] niet helemaal frisjes, aangezien a[2] niet bestaat.
a[2] bestaat wel degelijk, je moet er alleen niet naar gaan schrijven want dan gaat het fout.

a[2] is hier wat bij een container de end() iterator is.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Zoijar schreef op 06 maart 2004 @ 13:54:
Read-after-write? Of veroorzaakt dat tegenwoordig geen stall meer? Ben er een beetje uit, het assembler gebeuren...laatste dat ik ken is pentium (1).

(bestaat STOSTW, store-string-word, nog, of is dat traag?)
STOSB/W/D bestaat nog, maar dat is altijd al traag geweest.
En met out-of-order execution maakt RaW niet zoveel meer uit (gok ik).
farlane schreef op 06 maart 2004 @ 13:56:
a[2] bestaat wel degelijk, je moet er alleen niet naar gaan schrijven want dan gaat het fout.

a[2] is hier wat bij een container de end() iterator is.
a[2] lezen is ook niet zo'n goed idee.
En a + 2 is de iterator, niet a[2].

[ Voor 28% gewijzigd door Olaf van der Spek op 06-03-2004 14:03 ]


  • Elijan9
  • Registratie: Februari 2004
  • Laatst online: 18:01
Waarom doe je trouwens niet gewoon een memcpy in combinatie met een static, de header is toch altijd hetzelfde?
C++:
1
2
3
4
5
6
7
8
9
10
11
12
static unsigned char gzip_header[10] = {
  0x1f,
  0x8b,
  Z_DEFLATED,
  0,
  0,
  0,
  0,
  0,
  0,
  3
};


edit:
Ehm, laat maar, MadWizard was me voor... Moet wat vaker refreshen ;)

[ Voor 23% gewijzigd door Elijan9 op 06-03-2004 14:38 . Reden: madwizard was me voor ]

War is when the young and stupid are tricked by the old and bitter into killing each other. - Niko Bellic


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Elijan9 schreef op 06 maart 2004 @ 14:35:
Waarom doe je trouwens niet gewoon een memcpy in combinatie met een static, de header is toch altijd hetzelfde?
Nu wel, maar meestal niet. In veel functies die met binary streams werken gebruik ik dit soort code (*r++, *w++) en het leek hier ook een redelijke optie.

  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

OlafvdSpek schreef op 06 maart 2004 @ 13:54:
Welke versie van VC is dat?
7.1 (2003)
Perfect is de code niet, want met drie movs ben je in principe klaar en heb je GZIP_HEADER_VALS helemaal niet nodig.
Nee inderdaad, vreemd dat ie niet gewoon immediate values gebruikt. Hij zal wel niet ver genoeg kijken om te zien dat de source ook echt constant is.

Handmatig in een loop de bytes kopieren levert trouwens 10 mov's op, ook daar voegt ie ze niet samen tot 3 mov's. Wel gebruikt ie voor de 0 bytes CL (die op 0 staat), dus hij kijkt wel naar de data.
Zoijar schreef op 06 maart 2004 @ 13:54:
Alleen dit?
GAS:
1
2
mov     ecx, dword ptr [_GZIP_HEADER_VALS]
mov     dword ptr [eax], ecx

Read-after-write? Of veroorzaakt dat tegenwoordig geen stall meer? Ben er een beetje uit, het assembler gebeuren...laatste dat ik ken is pentium (1).
Waarschijnlijk wordt er wel het een en ander gereordered, zodat er bijvoorbeeld 2 dwords gelezen worden en dan 2 geschreven. Daar zitten ook allemaal weer regels aan vast enzo maar volgens mij is er wel flink wat verbeterd sinds de eerste pentium.
(bestaat STOSTW, store-string-word, nog, of is dat traag?)
stosw (of beter stosd want die is voor 32-bit) en movsd (memcopy) zijn op zich traag, behalve wanneer je ze in cobinatie met 'rep' en op grote blokken data gebruikt. Hier dus niet erg snel, maar als je een flink blok data moet kopieren (en de boel is aligned enzo) kopieert 'rep movsd' een hele cacheline per keer en dat gaat best snel.

www.madwizard.org


Verwijderd

Verwijderd schreef op 06 maart 2004 @ 09:53:
Wat is hier de bedoeling van? Zou het dit niet moeten zijn:

C++:
1
2
char a[2] = {0, 0};
char* w = a;
?
Nee, het ging mij er alleen maar om, om exact na te bootsen wat de TS wilde in de oorspronkelijke code, dus {0,0} op positie 0 en 1, en dat w na afloop wijst naar het derde element...

Verwijderd

Zoijar schreef op 06 maart 2004 @ 13:54:
Alleen dit?
GAS:
1
2
mov     ecx, dword ptr [_GZIP_HEADER_VALS]
mov     dword ptr [eax], ecx

Read-after-write? Of veroorzaakt dat tegenwoordig geen stall meer? Ben er een beetje uit, het assembler gebeuren...laatste dat ik ken is pentium (1).
De enige read die hier na een write plaatsvind, is een write naar ecx (een intern register) en een read daarvan... Gelukkig heeft een read-after-write van een register (registerinhoud, niet "registergeindexeerd adres") toch nog nooit problemen opgelevert, ook vroeger op een 386 niet, behalve een write naar de program-counter dan. ;)

Het wegschrijven naar een geheugenadres en direct weer inlezen geeft vooral stalls, toch :?

[ Voor 5% gewijzigd door Verwijderd op 08-03-2004 11:27 . Reden: niet over registergeindexeerd memory-access ]


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Verwijderd schreef op 08 maart 2004 @ 10:10:
[...]

De enige read die hier na een write plaatsvind, is een write naar ecx (een intern register) en een read daarvan... Gelukkig heeft een read-after-write van een register toch nog nooit problemen opgelevert, ook vroeger op een 386 niet, behalve een write naar de program-counter dan. ;)

Het wegschrijven naar een geheugenadres en direct weer inlezen geeft alleen maar stalls, toch :?
Nee, sinds de 486 is de architectuur pipelined. Reads after writes kunnen ook dan stalls opleveren.

Verwijderd

OlafvdSpek schreef op 08 maart 2004 @ 10:21:
Nee, sinds de 486 is de architectuur pipelined. Reads after writes kunnen ook dan stalls opleveren.
Ook op registers?

Dan heb je het -neem ik aan- eigenlijk over een read van een register die gebruikt moet worden om voor dataprefecting, 1 van de eerste stappen in de pipeline... Dan is het niet zozeer de read van het register die een stall geeft, maar het feit dat de data-prefetch prediction niet al vroeg van te voren weet in welk gedeelte van het data de geindexeerde read of write operatie gaat plaatsvinden. Dat noem ik een caching probleem, en geen read-after-write stall, meer een data fetching-stall.

Zoals bijvoorbeeld
GAS:
1
2
    MOV ecx, dword ptr [_GZIP_HEADER_VALS_PTR]
    MOV ecx, dword ptr [ecx]


Of heb ik dit altijd verkeerd begrepen...? Lijkt mij toch ook niet als VC dit ook genereert...

[ Voor 1% gewijzigd door Verwijderd op 08-03-2004 10:41 . Reden: verkeerd voorbeeld, een "mov constant naar register" kan wel ge-predicted worden... |:( ]


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Ja.
Dan heb je het -neem ik aan- eigenlijk over een read van een register die gebruikt moet worden om voor dataprefecting, 1 van de eerste stappen in de pipeline... Dan is het niet zozeer de read van het register die een stall geeft, maar het feit dat de data-prefetch prediction niet al vroeg van te voren weet in welk gedeelte van het data de geindexeerde read of write operatie gaat plaatsvinden. Dat noem ik een caching probleem, en geen read-after-write stall, meer een data fetching-stall.

Zoals bijvoorbeeld
GAS:
1
2
    MOV ecx, dword ptr [_GZIP_HEADER_VALS_PTR]
    MOV ecx, dword ptr [ecx]


Of heb ik dit altijd verkeerd begrepen...? Lijkt mij toch ook niet als VC dit ook genereert...
Jij noemt het data-prefetching, maar volgens mij gaat het gewoon over data-fetching. En of ecx nou nodig is om een adres te berekenen of om wat anders te berekenen maakt niet uit, als een waarde nodig is voordat die waarde bekend is heb je een stall.

Door out-of-order execution kan de CPU waarschijnlijk andere instructies uitvoeren, dus heb je geen last van de stall.

Verwijderd

OlafvdSpek schreef op 08 maart 2004 @ 10:48:
Jij noemt het data-prefetching, maar volgens mij gaat het gewoon over data-fetching.
Early datafetching, undelayed datafetching, data prefetching, etc. Ligt maar aan welk boek je als eerste gelezen hebt...

Late/delayed feching veroorzaakt een stall, buiten de tijd die het (altijd) kost om data te fetchen, omdat het de pipeline ophoudt. De tijd die het kost om data op te halen heet -voorzover ik weet- geen "stall". Alleen het ophouden van de pipline wordt daarmee aangeduid, dus misschien gebruik je de verkeerde termen maar bedoel je hetzelfde?
En of ecx nou nodig is om een adres te berekenen of om wat anders te berekenen maakt niet uit, als een waarde nodig is voordat die waarde bekend is heb je een stall.
Alleen vind het schrijven van de waarde naar ecx in de eerste instructie van de oorspronkelijke code (mov <register>, dword ptr [<constante>]), en het lezen van de waarde van ecx in de tweede instructie op hetzelfde deel van de pipeline plaats en dus is er geen stall, die is er alleen als een eerdere stap in de pipeline het resultaat van een latere stap in de pipeline van de vorige instructie(s) nodig is... En dat is alleen het geval

[ Voor 7% gewijzigd door Verwijderd op 08-03-2004 11:09 . Reden: qoute => quote ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22-05 16:53
OlafvdSpek schreef op 06 maart 2004 @ 14:02:
a[2] lezen is ook niet zo'n goed idee.
En a + 2 is de iterator, niet a[2].
Hmm, was ook eigenlijk &a[2].

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.

Pagina: 1