Dataprodukter i en pipelinerad processor inträffar när ett datamissberoende finns mellan instruktioner, vilket innebär att en instruktion behöver resultatet av en tidigare instruktion innan det resultatet är tillgängligt. Detta kan stoppa rörledningen och minska effektiviteten. Flera tekniker mildrar dessa faror:
1. Data vidarebefordran (förbikoppling):
* Mekanism: Detta är den vanligaste och effektiva metoden. Om resultatet av en instruktion i ett senare skede av rörledningen behövs av en instruktion i ett tidigare skede, vidarebefordras resultatet direkt från det senare skedet till det tidigare skedet, genom att kringgå minnesåtkomst.
* Exempel: Låt oss säga instruktioner i1 skriver för att registrera R1, och instruktion i2 läser från R1. Data vidarebefordran skulle skicka värdet skrivet av i1 direkt till i2, vilket förhindrar en stall även om I1 inte har slutfört sin skrivning till minnet.
* Effektivitet: Mycket effektiv för att lösa råa (läs efter skrivning) faror där beroendet är mellan instruktioner att skriva och sedan läsa samma register.
2. Stalling (bubbelinsättning):
* Mekanism: Om dataförstärkning inte är möjlig (t.ex. beroendet är för långt ifrån varandra i rörledningen, eller involverar minnesåtkomst), stannar rörledningen genom att infoga "bubblor"-no-op-instruktioner-tills data är klara.
* Exempel: I1 skriver till minnet, och i2 läser från den minnesplatsen. Data vidarebefordran är inte genomförbar eftersom I1:s skrivning måste slutföras innan I2 kan läsa. Rörledningen stannar tills i1 slutför sin skrivning.
* Effektivitet: Enklare att implementera än vidarebefordran men minskar avsevärt rörlednings genomströmning.
3. Registrera byte:
* Mekanism: Kompilatorn eller hårdvaran tilldelar olika register till instruktioner som kan ha ett databeroende. Detta eliminerar kriget (skriv efter läsning) och WAW (skriv efter skriv) faror. Till exempel, om två instruktioner använder samma register, kan hårdvaran byta namn på en av dem till ett annat register och därmed lösa konflikten.
* Exempel: Två instruktioner vill skriva till R1. Register Benaming tilldelar den andra instruktionen ett annat tillfälligt register och löser WAW -risken.
* Effektivitet: Mycket effektiv för att eliminera krigs- och WAW -faror, men innebär hårdvarukomplexitet. Används ofta i samband med dataförstörning.
4. Kompileringsoptimeringar:
* Mekanism: Kompilatorer kan analysera koden för databeroenden och ordna om instruktioner för att minimera faror. Detta kan involvera instruktionsplanering för att separera instruktioner som beror på varandra och därmed minska behovet av att stoppa eller vidarebefordra.
* Exempel: Kompilatorn kan ordna om instruktioner för att flytta instruktioner som läser data längre bort från instruktionerna som skriver dessa data och därmed ger rörledningen mer tid att avsluta innan den beroende instruktionen behöver det.
* Effektivitet: Minskar frekvensen av faror på källkodnivån, men effektiviteten beror på kompilatorns kapacitet.
Valet av begränsningsteknik beror på processorns specifika arkitektur. Moderna processorer använder vanligtvis en kombination av dataförstöring, registrering av byte och kompilatoroptimeringar för effektiv hantering av datafaror. Stalling används ofta som en sista utväg när andra tekniker är otillräckliga.