-
HINTERGRUND
-
Ein typisches modernes Computersystem kann einen Mehrkernprozessor beinhalten, der ein oder mehr Prozessorkerne beinhaltet, die viele Threads ausführen. Ein relativ komplexer Softwarestapel kann auf dem Mehrkernprozessor laufen und als solches kann eine gegebene Softwarefunktion, wie z. B. ein Zeichenaufruf, nicht seriell über den Satz an Prozessorkernen ausgeführt werden, sondern stattdessen wird die Funktion typischerweise in mehrere Tasks unterteilt, die über viele Threads auf den Prozessorkernen ausgeführt werden. Wenn zusätzlich ein spezifischer Task typisch ausführt, ist dies nicht deterministischer Natur, da jeglicher einzelner Task theoretisch von dem Scheduler vorab geleert, midstream von der Ausführung entfernt und zu späterer Zeit auf einem anderen Thread und/oder Kern erneut geschedult werden kann.
-
Angesichts dieser Komplexitäten kann es für ein Analyseprogramm zur Herausforderung werden, zu bestimmen, welche beobachteten Leistungsmetriken, wie z. B. Cache-Misses, Ausführungsblockierungen etc., einem spezifischen Task, einer Gruppe von Tasks oder einer Softwarefunktion zugeschrieben werden können.
-
KURZE BESCHREIBUNG DER ZEICHNUNGEN
-
1 ist ein schematisches Diagramm eines Computersystems gemäß einer erfindungsgemäßen Ausführungsform.
-
2 ist ein Ablaufdiagramm, das eine Technik darstellt, um einen gezählten Wert gemäß einer erfindungsgemäßen Ausführungsform auf einem auf einem Mehrkernprozessor ausgeführten Task aufzuteilen.
-
3 ist eine Veranschaulichung sich zeitlich überlappender Tasks, die gemäß einer erfindungsgemäßen Ausführungsform auf einem Mehrkernprozessor ausgeführt werden.
-
4 ist ein Ablaufdiagramm, das eine Technik darstellt, um ausgewählte Tasks gemäß des Prozessorkerns, auf dem die Tasks ausführen, gemäß einer erfindungsgemäßen Ausführungsform zu sortieren.
-
5A und 5B sind Ablaufdiagramme, die eine Technik darstellen, um einen gezählten Wert gemäß einer erfindungsgemäßen Ausführungsform auf ausgewählte Tasks aufzuteilen, die auf einem Prozessorkern ausführen.
-
AUSFÜHRLICHE BESCHREIBUNG
-
Mit Bezug auf 1 weist, gemäß erfindungsgemäßer Ausführungsformen, eine Mehrkernmaschine oder System 10 einen Mehrkern-Grafikprozessor 30 auf, der mehrere Prozessorkerne 34 aufweist. Jeder Prozessorkern 34 weist für dieses Beispiel einen Hardwarezähler 36 auf (wobei ein Zähler 36 pro Kern 34 in 1 dargestellt ist), um eine bestimmte Leistungsmetrik zu messen. Beispielsweise kann ein gegebener Prozessorkern 34 einen Hardwarezähler 36 beinhalten, um Cache-Misses zu zählen, einen Zähler 36, um die Anzahl an Ausführungsblockierungen zu zählen, einen Zähler 36, um eine Zählung zu verwalten, die für eine Ausführungsauslastung bezeichnend ist, etc. Es wird festgestellt, dass der Mehrkern-Grafikprozessor 30 lediglich ein Beispiel eines Mehrkernprozessors ist, da der hierin beschriebene Mehrkernprozessor kein Grafikprozessor sein muss, wie z. B. ein SIMD-(single instruction multiple data)-Mehrkernprozessor oder ein Hauptsystemprozessor 14 des Systems 10, als nicht einschränkende Beispiele.
-
Es wird hierin angenommen, dass die Prozessorkerne 34 Tasks ausführen, wobei ein Task jegliche übliche Arbeitseinheit zum Scheduling und zur Ausführung ist. Im Allgemeinen kann ein Task jeglicher Teil eines Codes mit einem Anfang und einem Ende sein, und die Dauer des Tasks kann als eine Anzahl an Prozessorzyklen definiert sein, um den Task auszuführen. Eine gegebene übergeordnete Softwarefunktion (im Falle von Grafikverarbeitung beispielsweise ein Zeichenaufruf) kann mehrere Tasks aufrufen, die über viele Threads auf mehreren Prozessorkernen 34 ausgeführt werden.
-
Der Hardwarezähler 36 ist kernspezifisch, sodass die Prozessorkerne 34 keinen Hardwarezähler pro Thread aufweisen. Stattdessen wird der Hardwarezähler 36 ohne Unterscheidung von den einzelnen Tasks geprüft, die auf dem Prozessorkern 34 laufen. Die fehlende Korrespondenz zwischen dem Hardwarezähler 36 und den Tasks kann zu Problemen beim Bestimmen führen, welcher Teil eines gezählten Wertes einem gegebenen Task zugeschrieben wird. Beispielsweise kann ein bestimmter Hardwarezähler 36 Cache-Misses für den gesamten Prozessorkern 34 zählen. Obwohl ein gegebener Task, der auf dem Prozessorkern 34 ausführt, den Hardwarezähler 36 am Anfang und Ende des Tasks prüfen kann, ist der von diesen Prüfungen abgeleitete gezählte Wert (d. h. das Zähl-Delta) nicht notwendigerweise bezeichnend für die Cache-Misses, die diesem gegebenen Task zugeschrieben werden können, da viele andere überlappende Tasks Cache-Misses während des Zeitintervalls hervorrufen können, währenddessen der gegebene Task aktiv ist.
-
Gemäß erfindungsgemäßer Ausführungsformen, die hierin beschrieben sind, führt das System 10 eine Technik durch, um gezählte Werte unter den Tasks aufzuteilen, die während einer gegebenen Zeitspanne ausführen. Um die folgende Erörterung zu vereinfachen, wird davon ausgegangen, dass der Hardwarezähler 36 ein Cache-Miss-Zähler ist, der von dem Prozessorkern 34 jedes Mal hochgezählt wird, wenn ein bestimmter Cache-Miss in dem Kern 34 auftritt. Die hierin beschriebenen Techniken können gemäß anderer erfindungsgemäßer Ausführungsformen angewendet werden, um gezählte Werte aufzuteilen, die mit anderen Metriken als Cache-Misses verbunden sind.
-
Mit Bezug auf 2 in Verbindung mit 1 führt das System 10 gemäß einiger erfindungsgemäßer Ausführungsformen eine Technik 100 durch, um einen Teil eines gezählten Wertes einem gegebenen Task zuzuschreiben, der auf einem Prozessorkern 34 ausführt. Die Technik 100 beinhaltet, dass Zählerdaten bereitgestellt werden (Block 104), die für einen gezählten Wert während eines Zeitsegments in dem mehrere Tasks auf dem Prozessorkern 34 aktiv sind, bezeichnend sind. Die Technik 100 beinhaltet, dass eine Wahrscheinlichkeit bestimmt wird (Block 108), dass der gezählte Wert einem gegebenen Task der Tasks während des Zeitsegments zugeschrieben werden kann, und einen Teil des gezählten Wertes dem gegebenen Task zumindest teilweise basierend auf der bestimmten Wahrscheinlichkeit, gemäß Block 112 zuzuschreiben.
-
Mit Bezug auf 1 führt der Grafikprozessor 30 gemäß einiger erfindungsgemäßer Ausführungsformen im Allgemeinen Tasks aus, um Bilder auf einem Display 40 zu generieren, wie z. B. einer beispielhaften dargestellten grafischen Benutzeroberfläche (graphical user interface, GUI) 44, die in 1 dargestellt ist. Die GUI 44 zeigt Tasks an, die auf dem Grafikprozessor 30 ausführen und erlaubt es einem Benutzer, ein oder mehr der Tasks zur Analyse auszuwählen. Als ein spezifischeres Beispiel kann die GUI 44 es gemäß einiger erfindungsgemäßer Ausführungsformen einem Benutzer erlauben, eine bestimmte Softwarefunktion (einen Zeichenaufruf als ein nicht einschränkendes Beispiel) hervorzuheben, um die Funktion zur Analyse von Leistungsmetriken auszuwählen, die mit diesem Aufruf verbunden sind. Die ausgewählte Funktion kann mehrere Tasks beinhalten, die auf dem Grafikprozessor 30 ausgeführt werden, kann mehrere Tasks beinhalten, die auf unterschiedlichen Threads ausführen, und kann Tasks beinhalten, die auf unterschiedlichen Prozessorkernen 34 ausgeführt werden.
-
Indem eine gegebene Softwarefunktion hervorgehoben und ausgewählt wird, kann ein Benutzer von einer Analyse profitieren, die von dem System 10 bereitgestellt wird, und diese Analyse kann nützlich sein, um zu bewerten, ob die Änderungen an Programmcode bestimmte Leistungsmetriken geändert haben. Beispielsweise kann die Leistungsanalyse aufdecken, dass Änderungen an dem Programm die Anzahl an Cache-Misses erhöht oder verringert haben. Andere und/oder unterschiedliche Verwendungen dieser Analyse werden in Betracht gezogen und liegen im Umfang der beigefügten Ansprüche.
-
Gemäß einiger erfindungsgemäßer Ausführungsformen kann die GUI 44 durch Ausführen eines Analyseprogramms betrieben werden, das auf ein oder mehr Prozessorkernen 34 ausführt. Bei anderen erfindungsgemäßen Ausführungsformen kann das Analyseprogramm das Ergebnis von Software sein, die auf dem Hauptsystemprozessor 14 des Systems 10 ausführt. Der Hauptprozessor 14 kann ein oder mehr Mikroprozessoren und/oder Mikroprozessorkerne beinhalten, die Anwendungen ausführen, wie z. B. ein Analyseprogramm. Der entsprechende Programmcode kann in einem Systemspeicher 18 gemäß einiger erfindungsgemäßer Ausführungsformen gespeichert sein. Auf diese Weise kann der Systemspeicher 18 Daten speichern, die für ein oder mehr Anwendungen 20 bezeichnend sind, die von dem Prozessor 14 ausgeführt werden. Eine der Anwendungen 20 kann beispielsweise ein Analyseprogramm sein, das, wenn es von dem Prozessor 14 ausgeführt wird, den Prozessor 14 veranlasst, ein oder mehr Teile der Technik 100 von 2 durchzuführen. Bei dieser Analyse kann der Speicher 18 ein oder mehr anfängliche, zwischenzeitliche oder endgültige Datensätze 22 speichern, die beispielsweise Auswahlen von Softwarefunktion oder Tasks durch den Benutzer; geprüfte Zählerwerte, die von auf dem Grafikprozessor 30 ausführenden Tasks geprüft werden; gezählte Werte, die spezifischen Tasks zugeschrieben werden können; mit den bestimmten gezählten Werten für die Tasks verbundene Fehler; etc. anzeigen können.
-
Unter den anderen Merkmalen des Systems 10 kann das System 10 eine Eingabe/Ausgabe-(I/O-Input/Output)-Schnittstelle 50 beinhalten, um I/O-Daten von solchen Eingabegeräten wie einer Maus oder einer Tastatur zu empfangen, die Tasks zur Analyse auswählen können. Das System 10 kann eine Netzwerkkarte (network interface card, NIC) beinhalten, um mit einem Netzwerk zu kommunizieren.
-
Es wird festgestellt, dass die Architektur, die in 1 dargestellt ist, lediglich ein Beispiel eines Mehrkernsystems ist, das verwendet werden kann, um die Techniken zur Aufteilung des gezählten Wertes, die hierin offenbart sind, zu implementieren. Beispielsweise können bei anderen erfindungsgemäßen Ausführungsformen über Verarbeiten auf dem Hauptprozessor 14 abgeleitete gezählte Werte auf Tasks aufgeteilt werden, die auf dem Prozessor 14 aktiv sind. Des Weiteren kann das System 10 zahlreiche andere Komponenten aufweisen, die nicht in 1 dargestellt sind, wie z. B. zusätzliche Grafikprozessoren, Bridges, Peripheriegeräte und andere Komponenten gemäß anderer erfindungsgemäßer Ausführungsformen.
-
3 stellt ein Beispiel dar, um zu veranschaulichen, wie das System 10 (1) einen gezählten Wert auf einem bestimmten Task gemäß einiger erfindungsgemäßer Ausführungsformen aufteilt. Mit Bezug auf 3 in Verbindung mit 1 wird für dieses Beispiel angenommen, dass mehrere Tasks 120 (speziell Tasks 1201, 1202, 1203 und 1204 als Beispiele) in überlappenden Zeitintervallen aktiv sind. Das Ziel für dieses Beispiel ist, einen Zähleränderungswert zu bestimmen, der der Ausführung des Tasks 1204 zugeschrieben werden kann. Wie aus 3 ersichtlich, führen Tasks 1201, 1202 und 1203 auf Threads T0, T1 bzw. T2 aus, und überlappen zumindest teilweise mit dem Task 1204, der auf Thread T4 ausführt. Die für dieses Beispiel besonders interessante Zeit ist Zeit t2 bis Zeit t5, während der der Task 1204 aktiv ist. Obwohl der Task 1204 Anfang und Ende von Zählerwerten bei Zeiten t2 bzw. t5 prüft, um einen gezählten Wert abzuleiten, zeigt dieser gezählte Wert nicht direkt einen gezählten Wert an, der einzig dem Task 1204 zugeschrieben werden kann.
-
Um die Änderung bei dem gezählten Wert dem Task 1204 zuzuschreiben, unterteilt das System 10 das Zeitintervall von Zeit t2 bis Zeit t5 in „Zeitscheiben”. In diesem Kontext ist eine „Zeitscheibe” eine Zeiteinheit, in der die Anzahl aktiver Tasks 120 sich nicht ändert. Setzt man dieses Kriterium ein, stellt das in 3 dargestellte Beispiel daher drei relevante Zeitscheiben dar, um den gezählten Wert auf dem Task 1204 aufzuteilen: eine erste Zeitscheibe von t2 bis Zeit t3, in der alle vier Tasks 1201, 1202, 1203 und 1204 aktiv sind; eine zweite Zeitscheibe von Zeit t3 bis Zeit t4, in der die Scheiben 1202, 1203 und 1204 aktiv sind; und eine dritte Zeitscheibe von Zeit t4 bis Zeit t5, in der die Tasks 1203 und 1204 aktiv sind.
-
Gemäß einiger erfindungsgemäßer Ausführungsformen prüft jeder Task 120 idealerweise den Hardwarezähler 34 am Anfang und Ende des Tasks 120. Daher wird für die vier Tasks 1201, 1202, 1203 und 1204, die in 3 dargestellt sind, der Hardwarezähler 34 acht entsprechende Male geprüft. Als nicht einschränkendes Beispiel können die für die geprüften Zählerwerte bezeichnenden Daten auf dem Grafikprozessor 30 gespeichert werden und/oder können dem Speicher 18 kommuniziert werden, wobei beispielsweise der gespeicherte Wert als ein Datensatz 22 gemäß einiger erfindungsgemäßer Ausführungsformen gespeichert wird.
-
Jede Zeitscheibe wird mit einem bestimmten gezählten Wert verbunden. Beispielsweise die Zeitscheibe von t2 bis Zeit t3 wird mit einem gezählten Wert verbunden, der von dem geprüften Zählerwert abgeleitet ist, der bei Zeit t3 genommen wird, minus des geprüften Zählerwertes, der bei Zeit t2 angezeigt wird. Für jede Zeitscheibe teilt das System 10 den verbundenen gezählten Wert auf dem Task 1204 gemäß einer bestimmten Wahrscheinlichkeit auf, dass der Task 1204 den Zählerwert während dieser Zeitscheibe geändert hat. Somit ist für die Zeitscheibe von Zeit t0 bis Zeit t1 der Teil des gezählten Wertes, der dem Task 1204 zugeschrieben werden kann, Null; und ebenso ist für die Zeitscheibe von Zeit t1 bis Zeit t2 der Teil des gezählten Wertes, der dem Task 1204 zugeschrieben werden kann, Null, da der Task 1204 während dieser Zeitscheiben nicht aktiv ist. Für die verbleibenden Zeitscheiben jedoch, die in 3 dargestellt sind, ist der Task 1204 aktiv, und somit schreibt das System 10 einen Teil des gezählten Wertes dem Task 1204 zu.
-
Nachdem das System 10 den aufgeteilten gezählten Wert für jede Zeitscheibe des Tasks 1204 bestimmt hat, führt das System 10 eine Summierung der aufgeteilten gezählten Werte durch, um einen aufgeteilten gezählten Wert für den Task 1204 vom Anfang des Tasks bei Zeit t2 bis zum Ende des Tasks bei Zeit t5 abzuleiten.
-
Als spezifischeres Beispiel ist für die Zeitscheibe von Zeit t2 bis Zeit t3 der Task 1204 gleichzeitig mit den Tasks 1201, 1202 und 1203 aktiv. Als nicht einschränkendes Beispiel schätzt das System 10 die Wahrscheinlichkeit für den Task 1204 als ein Viertel des gezählten Wertes während dieser Zeitscheibe ab, da vier Zeitscheiben aktiv waren. Wenn sich somit beispielsweise der Zähler bei 100 Zählungen während der Zeitscheibe von Zeit t2 bis Zeit t3 ändert, wird ein Viertel, oder eine Zähleränderung von 25, dem Task 1204 für diese Zeitscheibe zugeschrieben. Während der Zeitscheibe von Zeit t3 bis Zeit t4 ist der Task 1204 mit zwei anderen Zeitscheiben 1202 und 1203 aktiv; und demzufolge wird ein Drittel des verbundenen gezählten Wertes dem Task 1204 während dieser Zeitscheibe zugeschrieben. Ebenso ist während der Zeitscheibe von Zeit t4 bis Zeit t5 der Task 1204 mit dem Task 1203 aktiv; und demzufolge schreibt das System 10 eine Hälfte des gezählten Wertes dem Task 1204 während dieser Zeitscheibe zu.
-
Die vorstehend beschriebene proportionale Aufteilung des gezählten Wertes basierend auf der Anzahl an Tasks, die aktiv sind, ist ein Beispiel einer von vielen unterschiedlichen möglichen Arten, den gezählten Wert aufzuteilen. Gemäß anderer erfindungsgemäßer Ausführungsformen beispielsweise kann die Aufteilung des gezählten Wertes auf einem Gewichtungsschema basieren. Beispielsweise kann den Tasks 120, die rechenintensiver sind, eine höhere Gewichtung zugeordnet werden, und somit kann ihnen eine unverhältnismäßig größere Menge des gezählten Wertes zugeordnet werden als im Vergleich zu Tasks, die weniger rechenintensiv sind. Somit werden viele Varianten in Betracht gezogen und liegen im Umfang der beigefügten Ansprüche.
-
Mit Bezug auf 4 in Verbindung mit 1 führt das System 10 gemäß einiger erfindungsgemäßer Ausführungsformen eine Technik 150 durch, um Tasks zu identifizieren, die auf den spezifischen Prozessorkernen 34 analysiert werden sollen. Gemäß der Technik 150 empfängt das System 10 eine Benutzereingabe, die für ausgewählte Tasks bezeichnend ist, gemäß Block 154. Somit kann ein Benutzer, als Beispiel, über die GUI 44 einen bestimmten Aufruf (einen Zeichenaufruf als nicht einschränkendes Beispiel) beispielsweise unter Verwendung einer Maus hervorheben und auswählen. In Antwort auf die ausgewählten Tasks bestimmt das System 10 (Block 158) alle Tasks, die zeitlich mit den ausgewählten Tasks überlappen gemäß Block 158. Nach dieser Identifizierung sortiert das System 10 (Block 162) die analysierten Tasks gemäß Prozessorkern 34 gemäß Block 162.
-
Mit Bezug auf 5A und 5B in Verbindung mit 1, führt das System 10 gemäß einiger erfindungsgemäßer Ausführungsformen eine Technik 200 für jeden Prozessorkern 34 durch, nachdem das System 10 die auf jedem Prozessorkern 34 zu analysierenden Tasks bestimmt hat.
-
Gemäß der Technik 200 verarbeitet das System 10 jeden ausgewählten Task auf jedem Prozessorkern 34 wie folgt. Zuerst identifiziert (Block 204) das System 10 Zeitscheiben für den nächsten verfügbaren Task und ruft geprüfte Zählerwerte für die Anfangs- und Endzeiten eines jeden Tasks ab (Block 208). Das System 10 kann die Anfangs- und/oder Endzeit interpolieren, wenn eine Prüfung nicht verfügbar ist. Auf diese Art und Weise bestimmt das System 10 (Raute 212), ob eine Interpolation einer Prüfung benötigt wird, und wenn ja, führt es die Interpolation gemäß Block 214 durch.
-
Gemäß einiger erfindungsgemäßer Ausführungsformen führt das System 10 die Prüfinterpolation wie folgt durch. Das System 10 findet den nächsten geprüften Zählerwert auf beiden Seiten der Zeit, bei der eine Prüfung interpoliert werden soll. Basierend auf dem Ort dieser Zeit zwischen den beiden Zeiten an denen Prüfungen verfügbar sind, stellt das System 10 den Unterschied bei den geprüften Werten ein, um den interpolierten Wert abzuleiten. Dies kann eine lineare Interpolation gemäß einiger erfindungsgemäßer Ausführungsformen sein. Als nicht einschränkendes Beispiel können Prüfwerte für Prozessorzyklus-Zählungen 100 und 200 verfügbar sein, und diese Werte können Werte 300 bzw. 360 aufweisen. Die Zeit, bei der die Prüfung interpoliert werden soll, kann Prozessorzyklus-Zählung 120 sein. Daher wäre für dieses Szenario die interpolierte Prüfung 312.
-
Noch immer mit Bezug auf 1, 5A und 5B geht eine Überprüfung nach einer möglichen Interpolation eines oder mehrerer Prüfwerte zu Raute 218 weiter, bei der das System 10 bestimmt, ob einem bestimmten Task ein Anfangs- oder Endzeitstempel fehlt. Wenn ja, dann erzeugt das System 10 gemäß Block 222 einen entsprechenden Zeitstempel, indem die nächste Anfangs- oder Endzeit eines weiteren Tasks gefunden wird.
-
Nachdem die Daten wie vorstehend gegeben vorausgesetzt wurden, geht das System 10 gemäß der Technik 200 weiter, um den gezählten Wert für jede Zeitscheibe des analysierten Tasks gemäß der Zeitscheiben des Tasks aufzuteilen. Auf diese Art und Weise bestimmt das System 10 gemäß Block 226 einen gezählten Wert für jede Zeitscheibe und bestimmt (Block 230) für jede Zeitscheibe die Wahrscheinlichkeit, dass der gezählte Wert durch den Task bedingt ist. Als nächstes teilt das System 10 (Block 234) den gezählten Wert für jede Zeitscheibe basierend auf der bestimmten Wahrscheinlichkeit auf und summiert daraufhin die aufgeteilten gezählten Werte für alle Zeitscheiben des analysierten Tasks gemäß Block 238, um einen aufgeteilten gezählten Wert für den gesamten Task abzuleiten.
-
Schließlich gibt das System 10 (Block 242) gemäß der Technik 200 den aufgeteilten gezählten Wert für den Task und einen Wert, der für den Fehler in dem bestimmten gezählten Wert bezeichnend ist, aus. Als nicht einschränkendes Beispiel kann der Fehler mit jeder Zeitscheibe zusammen mit dem aufgeteilten Wert berechnet werden. Wenn beispielsweise für eine bestimmte Zeitscheibe der aufgeteilte gezählte Wert aufgrund zweier anderer Tasks, die gleichzeitig in der Zeitscheibe aktiv sind, dreiunddreißig Prozent der gesamten Zeitänderung für die Zeitscheibe beträgt, dann wäre der berichtete Fehler der Prozentsatz des verbleibenden aufgeteilten gezählten Wertes oder siebenundsechzig Prozent. Es wird festgestellt, dass der Fehler mit entsprechend zunehmender Anzahl gleichzeitig aktiver Tasks abnimmt. Somit ist der Fehler für eine ziemlich große Anzahl aktiver Tasks, wie z. B. mehrere tausend Tasks, relativ gering.
-
Schließlich bestimmt das System 10 gemäß der Technik 200, ob ein weiterer Task für den Prozessorkern analysiert werden soll gemäß Raute 246. Wenn ja, kehrt die Überprüfung zu Block 154 (5A) zurück.
-
Obwohl die vorliegende Erfindung im Hinblick auf eine begrenzte Anzahl von Ausführungsformen beschrieben wurde, werden für Fachleute, die den Vorteil dieser Offenbarung kennen, zahlreiche Modifikationen und Varianten davon selbstverständlich sein. Es ist beabsichtigt, dass die beigefügten Ansprüche alle solchen Modifikationen und Varianten abdecken, die dem Sinn und Umfang dieser vorliegenden Erfindung entsprechen.