Auf was für einer CPU werden die Programme ausgeführt? Welche ISA-Erweiterungen werden unterstützt?
Die Architektur des Aufgabentesters ist x86-64, welche die SSE/SSE2-Erweiterungen unterstützt, nicht aber neuere Erweiterungen. MMX und die x87 FPU werden nicht unterstützt.
Was bedeutet die Bewertung?
Ein Programm wird mit verschiedenen Eingaben ausgeführt, woraus die durchschnittliche Anzahl an Zyklen, die das Programm benötigt, errechnet wird.
Wenn Zyklen gemessen werden, ist das Ergebnis dann nicht ungenau?
Auf echter Hardware wäre das der Fall. Daher werden die Programme in einem CPU-Emulator (Raspsim) ausgeführt. Dadurch ist die Ausführungsumgebung immer gleich und die Zahl der benötigten Zyklen reproduzierbar.
Warum ändert sich die Zyklenzahl nicht, wenn ich ein mov
/nop
hinzufüge?
Es wird ein Core mit Out-of-Order Execution emuliert, der Instruktionen umordnen und auch parallel ausführen kann. Genauere Informationen was in den einzelnen Zyklen passiert kann unter Traces anzeigen erhalten.
Wie kann ich Code im Tester debuggen?
Zu Debugging-Techniken im Tester gibt es eine separate Seite.
Warum funktioniert mein Code im Simulator nicht, aber auf echter Hardware?
Der häufigste Grund dafür ist, dass der Code zwar fehlerhaft ist, aber der Fehler auf echter Hardware nicht auftritt. Es kann sich aber auch um einen Bug des Simulators handeln: Bekannte Bugs des Simulators sind auf einer separaten Seite aufgelistet.
Was ist ein Page Fault? Sollte das nicht ein Segmentation Fault sein? Was bedeutet der Fehlercode?
Im Emulator gibt es kein Betriebssystem, welches die CPU-Exceptions auf Signale (man 7 signal
) abbildet. Deshalb werden einfach die CPU-Exceptions direkt angezeigt. Im Register cr2
steht die Adresse, die den Page Fault ausgelöst hat. Der Fehlercode (errcode
) gibt Informationen dazu, welche Operation den Page Fault ausgelöst hat. Die Bedeutung des Fehlercodes ist im Intel SDM Vol. 3, Abschnitt 4.7 (Page-Fault Exception) dokumentiert.
Was ist ein Memory Mismatch? Wie ist die Ausgabe zu interpretieren?
In manchen Aufgaben muss das Ergebnis in einen Speicherbereich geschrieben werden. Falls dieser Speicherbereich zum Ende der Funktion nicht die erwarteten Daten enthält, gibt der Aufgabentester die Unterschiede aus. Hierbei wird immer die Speicheradresse und der erwartete im Vergleich zum erhaltenen Wert in Hexadezimal ausgegeben.
An welcher Adresse liegt der Code im Speicher? Wie sehe ich, wo eine Exception aufgetreten ist?
Die Adresse ist zufällig, der Code beginnt aber immer an einer 4-kiB-Page. Zusätzlich wird, sofern möglich, auch die Zeilennummer der verursachenden Instruktion neben dem Wert des Registers rip
angezeigt.
Welche Größenbeschränkungen gibt es?
Bei den meisten Aufgaben sind die Größe des kompilierten Codes (einschließlich konstanter Daten) sowie des Stack jeweils auf 4 kiB begrenzt. Abweichungen davon können bei den Aufgaben angegeben sein.
Was bedeutet ein Timeout?
Ein Timout bedeutet, dass der Testvorgang zu lange gedauert hat. Dies ist in der Regel auf einen ineffizienten Lösungsansatz zurückzuführen; das Problem lässt sich meist durch algorithmische Optimierungen am eigenen Code vermeiden.
Meine Abgabe hängt auf Testing, warum?
Dann gibt es vermutlich ein Problem beim Testen; am besten das Programm nach ein paar Minuten nochmal abgeben. Wenn das Problem weiter besteht, handelt es sich vmtl. um einen Bug, wo wir uns über eine Information freuen würden, siehe unten.
Ich glaube, ich habe einen Fehler gefunden.
Bitte eine E-Mail an openasp@aengelke.net schreiben.
Was ist eine ABI Violation?
Bestimmte Register müssen am Ende der Funktion denselben Wert haben wie zu Beginn der Funktion. Die Register können entweder zu Beginn auf dem Stack gespeichert werden (push
) und am Ende wiederhergestellt werden (pop
); oder es kann auf andere Register ausgewichen werden.
Warum funktioniert .section
nicht?
An sich funktioniert .section
schon. Allerdings sind Abgaben derzeit auf read-only Speicher beschränkt, sodass nur die Abschnitte .text
und .rodata
benutzt werden können. Eigene schreibbare Datenbereiche sollten Sie für die Aufgaben auch nicht benötigen und globale Variablen sollten allgemein eher vermieden werden.
Was bedeutet relocation truncated to fit?
Der Code im Simulator wird bei den meisten Aufgaben an eine zufällige Adresse geladen, sodass die Adressen von globalen Variablen meist nicht in 32 Bit codiert werden können. Abhilfe kann mit der Nutzung von RIP-relativer Adressierung geschaffen werden:
.section .rodata
.Lmyconst: .int 4
.text
myfunc:
mov eax, [rip + .Lmyconst]
ret
Warum kommt bei der Verwendung von manchen Instruktionen #NM
?
SSE-Instruktionen stehen nicht bei allen Aufgaben zur Verfügung. Instruktionen der Legacy x87 FPU und der MMX-Erweiterung sind nicht unterstützt.
Was bedeutet der Fehler Invalid ELF: contains writable segment
?
Derzeit sind alle Abgaben auf read-only Speicher beschränkt, sodass schreibbare globale und statische Variablen nicht genutzt werden können.
Warum funktioniert #include <stdlib.h>
nicht?
C-Code wird im Aufgabentester als Freestanding-Code ohne Standard-Library kompiliert. Deshalb stehen auch nur bestimmte Header zur Verfügung (z.B. stdint.h
, stddef.h
, oder auch immintrin.h
), nicht aber Header, die zur Standard-Library oder zum Betriebssystem gehören.
Wie kann ich dynamisch Speicher alloziieren?
In einem sehr begrenzten Umfang kann Stack-Speicher alloziiert werden, da aber insbesondere keine Standard-Library vorhanden ist, werden andere Mechanismen wie malloc()
derzeit nicht unterstützt.
Mein Code kompiliert mit Warnungen, funktioniert aber. Kann ich die ignorieren?
Bitte nicht! Die meisten Compiler-Warnungen deuten auf ein (möglicherweise verdecktes) Problem hin, was nur im konkreten Fall nicht auftritt. Generell sollte jeder C-Code ohne Warnungen, einschließlich derer, die durch -Wall
und -Wextra
aktiviert werden, kompilieren.
Welcher Compiler wird verwendet?
gcc (Alpine 12.2.1_git20220924-r10) 12.2.1 20220924
Welche Compiler-Optionen werden verwendet?
Als Optimierungsstufe kommt -O3
zum Einsatz, der verwendete C-Standard ist C11/C17 (-std=c17
) und es werden einige Warnungen aktiviert (-Wall -Wextra -Wpedantic
). Alle konkret verwendeten Optionen werden bei einer Abgabe mit Kompilierfehlern angezeigt. Die meisten der Optionen sind aber nur für die spezielle Umgebung im Aufgabentester notwendig (etwa, dass keine Standard-Library vorhanden ist).