Ray voor de Nieuwsgierigen

Dean Wampler

Volg

Dec 19, 2019 · 10 min lezen

(Verfijningen Februari 8, 2020)

TL;DR Ray is een systeem voor het schalen van Python applicaties over het berekenen van clusters met een minimale inspanning. Dit bericht legt de problemen Ray oplost en hoe het te gebruiken.

Het Ray-Project lokaal,
The Ray Project, beschikbaar op https://ray.io

Ray (website, GitHub) is een open-source systeem voor het schalen van Python toepassingen van enkele machines tot grote clusters. Het ontwerp wordt gedreven door de unieke behoeften van de volgende generatie ML/AI-systemen, die worden geconfronteerd met verschillende unieke uitdagingen, waaronder diverse computationele patronen, beheer van gedistribueerde, evoluerende toestand, en de wens om al die behoeften met minimale programmering inspanning.

typische ML / AI-systemen vereisen uiteenlopende computationele patronen ter ondersteuning van gegevensreiniging en-voorbereiding, hyperparameter-afstemming, modeltraining en-bediening en andere taken. Het originele MapReduce-model voor big data-workloads werkt goed voor gegevensreiniging, voorbereiding en ook voor analyse-workloads, maar machine learning-workloads vereisen een mix van fijnkorrelige tot grofkorrelige taken, samen met gevarieerde communicatiepatronen tussen componenten. Hyperparameter-tuning en modeltraining zijn zeer rekenintensief, waardoor clusterbronnen binnen redelijke termijnen moeten worden voltooid. Ray biedt de basis voor het bouwen van moderne ML/AI-systemen en toepassingen door te voldoen aan deze diverse eisen op een performante manier, met een minimale en intuã tieve API.

een tweede uitdaging wordt verspreid, waarbij de toestand zich ontwikkelt. In de context van ML/AI, distributed state omvat de hyperparameters, modelparameters (bijvoorbeeld, en voor versterking leren scenario ‘ s, de toestand van simulaties (of interacties met de echte wereld) gebruikt voor training. Vaak is de staat veranderlijk, vooral tijdens de training, dus voorzichtig, concurrency-veilige updates zijn vereist. Een mogelijke manier van omgaan met gedistribueerde computing is om populaire “serverless” systemen te exploiteren, maar geen biedt momenteel faciliteiten voor het beheer van gedistribueerde, veranderlijke toestand. Ontwikkelaars moeten hun toevlucht nemen tot het houden van alle staat in een database bij het gebruik van serveless systemen, maar de database kan een bottleneck en een enkel punt van mislukking zijn.

in plaats daarvan gebruikt Ray het populaire Actor model om een intuïtief mechanisme te bieden voor state management. Ray acteurs bieden een stateful aanvulling op ray taken, die stateloos zijn. Deze status is transparant bereikbaar voor elke andere Ray-actor of taak door middel van een verwijzing naar het corresponderende Python-object (dat wil zeggen, een instantie van een Python-klasse). Ray houdt bij waar de actor zich in het cluster bevindt, waardoor het niet nodig is om dergelijke locaties expliciet te kennen en te beheren in gebruikerscode. Mutatie van toestand in de actor wordt behandeld op een thread-veilige manier, zonder de noodzaak van expliciete concurrency primitieven. Daarom biedt Ray intuã tief, gedistribueerd state management voor toepassingen, wat betekent dat Ray een uitstekend platform kan zijn voor het implementeren van stateful serverless applicaties, in het algemeen. Bovendien wordt bij het communiceren tussen acteurs of taken op dezelfde machine de status transparant beheerd door gedeeld geheugen, met nul-kopieer serialisatie tussen de acteurs en taken, voor optimale prestaties.

ten slotte, omdat de meeste ML/AI-systemen Python-gebaseerd zijn, hebben ontwikkelaars een manier nodig om deze scale-out mogelijkheden toe te voegen met minimale code veranderingen. Een decorateur, @ray.remote, markeert functies en klassen als logische eenheden die in een cluster kunnen worden geïnstalleerd en uitgevoerd. Ray behandelt op transparante wijze thread-safe mutatie van toestand, verdeling van toestand en intuïtieve planning van afhankelijke taken.

de Straaldistributie omvat verschillende high-performance bibliotheken gericht op AI-toepassingen, die ook motiverende problemen waren die de creatie van straal aandreven. Ze omvatten RLlib voor versterking leren en Tune voor hyperparameter tuning. Beide tonen Ray ‘ s unieke mogelijkheden. Deze bibliotheken en andere, aangepaste toepassingen geschreven met Ray worden al gebruikt in veel productie-implementaties.

Ray is een open source project gestart in de UC Berkeley RISELab. Het is nu ontwikkeld op elke schaal met belangrijke bijdragen van vele andere organisaties. Commerciële gebruikers van Ray zijn onder andere Ant Financial, JP Morgan, Intel, Microsoft, Ericsson, Skymind, Primer en vele anderen.

een voorbeeld van de core Ray API

opmerking: de volledige lijst van de volgende code voorbeeld kan worden gevonden aan het einde van deze post.

nu we de motivaties en voordelen van Ray begrijpen, laten we eens kijken hoe u de Ray API in uw toepassingen zou gebruiken. Dan zullen we beter kijken naar hoe Ray verbetert de prestaties door middel van parallellisatie en distributie. De Ray API is zorgvuldig ontworpen om gebruikers in staat te stellen hun toepassingen te schalen, zelfs over een cluster, met minimale code veranderingen.

beschouw het voorbeeld van een parameterserver, een sleutelwaardeopslag die wordt gebruikt voor het trainen van machine learning-modellen in een cluster. De waarden zijn de parameters van een machine-learning model (bijv., een neuraal netwerk). De toetsen indexeren de modelparameters. Als u niet bekend bent met parameterservers, denk dan aan een standalone service die u nodig heeft voor het ontvangen van verzoeken om informatie of gegevens.

in een filmaanbeveling kan er bijvoorbeeld één sleutel per gebruiker en één sleutel per film zijn. Voor elke gebruiker en film zijn er overeenkomstige gebruikerspecifieke en filmspecifieke parameters. In een taal-modellering toepassing, woorden kunnen de sleutels en hun inbeddingen kunnen de waarden zijn.

in zijn eenvoudigste vorm kan een parameterserver één sleutel hebben en toestaan dat alle parameters tegelijk worden opgehaald en bijgewerkt.

hier is een voorbeeld van zo ‘ n eenvoudige parameterserver, voor een enkele NumPy array van parameters. Het wordt geà mplementeerd als een Ray-actor in minder dan 15 regels code:

invoer en definitie van de parameterserveractor

de decorateur @ray.remote definieert een dienst. Het neemt de gewone Python klasse, ParameterServer, en laat het toe om te worden geïnstalleerd als een remote service. Omdat de instantie de status behoudt (de huidige parameters, die veranderlijk zijn), hebben we een stateful service.

in dit voorbeeld gaan we ervan uit dat een update van de parameters wordt gegeven als een gradiënt die moet worden toegevoegd aan de huidige parametervector. (Deze gradiënt kan een enkel getal zijn dat wordt toegevoegd aan alle array-elementen of een array van gradiënten.) Meer geavanceerde ontwerpen zijn mogelijk, natuurlijk, maar Ray zou worden gebruikt op dezelfde manier. Als een eenvoudige oefening, probeer dit te veranderen in een key-value (woordenboek) implementatie.

een parameterserver bestaat doorgaans als een proces of service op afstand. Clients communiceren met het door middel van externe procedure oproepen. Om de parameterserver als een remote actor te installeren, doen we de volgende stappen bij de interactieve Python prompt. (We gaan ervan uit dat u de ParameterServer klasse al hebt gedefinieerd in dezelfde sessie). Eerst moet je Ray starten. Wanneer u een cluster gebruikt, geeft u optionele parameters door aan de methode init() om de clusterlocatie op te geven:

Python interactieve sessie: start Ray

volgende, Maak een ParameterServer instance aan voor een array van 10 parameters:

construeer een parameterserver actor instance

in plaats van ParameterServer(10) aan te roepen om een instance te construeren, zoals je zou doen bij een normale Python instance, gebruik je in plaats daarvan de remote() methode, die aan de klasse is toegevoegd door de @ray.remote decorator. Je geeft dezelfde argumenten die je zou doorgeven aan de reguliere constructeur. Merk op dat een actor object is geconstrueerd.

om methoden op de actor aan te roepen, gebruikt u remote() die aan de oorspronkelijke method-naam is toegevoegd, waarbij u dezelfde argumenten doorgeeft die u aan de oorspronkelijke methode zou doorgeven:

een methode op afstand aanroepen

Actormethode aanroepen retourfutures. Om de werkelijke waarden op te halen, gebruiken we de blokkerende ray.get(id) aanroep:

waarden ophalen met ray.get (id)

zoals we verwachten, zijn de initiële parameterwaarden allemaal nullen. Wat ray.get(id) eigenlijk doet, is de waarde uit de gedistribueerde Statusopslag-service halen die Ray levert. De waarde is door de actor naar het gedistribueerde statusarchief geschreven toen de status werd bijgewerkt. Als de waarde en de client beide op dezelfde machine staan, wordt de waarde uit het gedeelde geheugen gehaald voor snelle prestaties. Als de waarde en de client resident zijn op verschillende machines, wordt de waarde getrokken naar de machine die het nodig heeft.

voor de volledigheid kan uw code ook waarden expliciet naar deze opslag schrijven met ray.put(id, value). Wanneer u meerdere waarden wilt ophalen als ze beschikbaar komen, is er een handige ray.wait(…) functie beschikbaar. Zie de Ray API voor meer informatie.

wanneer clients deze actormethoden aanroepen, worden de aanroepingen naar de actor-instantie geleid, waar deze zich ook in het cluster bevindt. Omdat gelijktijdige aanroepingen kunnen plaatsvinden, verzekert Ray dat elke aanroep op een thread-veilige manier wordt verwerkt, zodat het risico op beschadiging van de toestand wordt voorkomen zonder de noodzaak voor expliciete thread synchronisatiecode. Echter, dit legt geen enkele vorm van wereldwijde volgorde van wanneer deze aanroepingen worden verwerkt op; het is het eerst komt, het eerst maalt.

Noot: Vanwege de dynamische aard van Python, zou het mogelijk zijn geweest voor Ray om u toe te staan om de actor methoden aan te roepen zonder remote(), maar er werd besloten dat de expliciete code verandering nuttige documentatie is voor lezers van de code, omdat er belangrijke gevolgen zijn voor de prestaties bij het overschakelen van een lokale methode aanroep naar een RPC-achtige aanroep. Ook is het geretourneerde object nu anders, een toekomst, die het gebruik van de blokkerende aanroep, ray.get() vereist om de waarde te extraheren.

stel nu dat we meerdere werktaken willen uitvoeren die continu gradiënten berekenen en de modelparameters bijwerken. Elke werknemer zal draaien in een lus die de volgende drie dingen doet:

  1. krijg de laatste parameters.
  2. Bereken een update van de parameters.
  3. de parameters bijwerken.

deze workers zullen statenloos zijn, dus zullen we een Ray-taak (een remote-functie) gebruiken in plaats van een actor. De functie worker neemt een handvat naar de parameter Server actor als een argument, die de werktaak toestaat om methoden op de parameter server aan te roepen:

Definieer een externe werknemer die parameter updates

uitvoert, dan kunnen we twee van deze werktaken als volgt starten. Ray taken (functies) worden gestart met dezelfde remote() aanroep:

gebruik twee taken om parameterupdates gelijktijdig te berekenen

dan kunnen we de parameters van het driverproces herhaaldelijk ophalen en zien dat ze worden bijgewerkt door de werknemers:

herhaal queries voor de huidige parameterwaarden

wanneer de updates stoppen, zullen de uiteindelijke waarden 200 zijn.

merk op dat Ray het net zo gemakkelijk maakt om een remote service of actor op te starten als het is om een Python-klasse te definiëren. Handvatten naar de actor kunnen worden doorgegeven aan andere acteurs en taken om willekeurige en intuïtieve messaging en communicatiepatronen mogelijk te maken. De huidige alternatieven zijn veel meer betrokken. Bijvoorbeeld, overweeg hoe de equivalente Runtime service creatie en service handle passeren zou worden gedaan met GRPC, zoals in deze documentatie.

taken en actoren verenigen

we hebben gezien dat taken en actoren dezelfde Ray API gebruiken en op dezelfde manier worden gebruikt. Deze vereniging van parallelle taken en actoren heeft belangrijke voordelen, zowel voor het vereenvoudigen van het gebruik van Ray en voor het bouwen van krachtige toepassingen door compositie.

ter vergelijking: populaire dataverwerkingssystemen zoals Apache Hadoop en Apache Spark laten statenloze taken (functies zonder bijwerkingen) toe om te werken op onveranderlijke gegevens. Deze veronderstelling vereenvoudigt het algehele systeemontwerp en maakt het voor toepassingen gemakkelijker om te redeneren over juistheid.

echter, gedeelde veranderbare toestand is gebruikelijk in machine learning-toepassingen. Die toestand kan het gewicht zijn van een neuraal netwerk, de toestand van een simulator van een derde partij, of een weergave van interacties met de fysieke wereld. Ray ‘ s actor abstraction biedt een intuïtieve manier om veranderlijke toestand te definiëren en te beheren op een thread-veilige manier.

wat dit bijzonder krachtig maakt is de manier waarop Ray de actorabstractie verenigt met de taak-parallelle abstractie die de voordelen van beide benaderingen erft. Ray gebruikt een onderliggende dynamische taakgrafiek om zowel acteurs als statenloze taken in hetzelfde kader te implementeren. Als gevolg daarvan zijn deze twee abstracties volledig interoperabel. Taken en actoren kunnen worden gecreëerd vanuit andere taken en actoren. Beide retour futures, die kunnen worden doorgegeven aan andere taken of actor methoden om planning en gegevens afhankelijkheden in te voeren op een natuurlijke manier. Als gevolg daarvan, Ray-toepassingen erven de beste eigenschappen van zowel taken en acteurs.

hier zijn enkele kernconcepten die intern door Ray worden gebruikt:

dynamische Taakgrafieken: wanneer u een functie op afstand of een actormethode aanroept, worden taken toegevoegd aan een dynamisch groeiende grafiek, die Ray planningen en uitvoert over een cluster (of een enkele multi-core machine). Taken kunnen worden gemaakt door de toepassing” driver ” of door andere taken.

Data: Ray serialiseert gegevens efficiënt met behulp van de Gegevenslay-out van Apache Arrow. Objecten worden gedeeld tussen werknemers en acteurs op dezelfde machine door middel van gedeeld geheugen, waardoor de noodzaak van kopieën of deserialisatie wordt vermeden. Deze optimalisatie is absoluut cruciaal voor het bereiken van goede prestaties.

Scheduling: Ray gebruikt een gedistribueerde schedulingbenadering. Elke machine heeft zijn eigen planner, die de arbeiders en acteurs op die machine beheert. Taken worden ingediend door aanvragen en werknemers aan de planner op dezelfde machine. Van daaruit kunnen ze worden toegewezen aan andere werknemers of doorgegeven aan andere lokale planners. Hierdoor kan Ray aanzienlijk hogere taakdoorvoer bereiken dan wat kan worden bereikt met een gecentraliseerde scheduler, een potentiële bottleneck en single point of failure. Dit is essentieel voor veel machine learning toepassingen.

conclusie

systemen zoals parameterservers worden normaal geà mplementeerd en verzonden als standalone systemen met een niet-triviale hoeveelheid code, die meestal een standaardplaat zou kunnen zijn voor het verwerken van distributie, aanroep, state management, enz. We hebben gezien dat Ray ‘ s abstracties en functies het mogelijk maken om de meeste van die standaardplaat te elimineren. Vandaar, elke functie verbeteringen zijn relatief eenvoudig en uw productiviteit wordt gemaximaliseerd.

veel van de gemeenschappelijke diensten die we in de huidige productieomgevingen nodig hebben, kunnen op deze manier, snel en efficiënt worden geïmplementeerd. Voorbeelden zijn logging, stream processing, simulatie, model serveren, grafiek verwerking, en vele anderen.

ik hoop dat u deze korte introductie tot Ray intrigerend vond. Probeer het alsjeblieft en laat me weten wat je ervan vindt!

voor meer informatie

voor meer informatie over Ray, kijk op de volgende links:

  • Ray website
  • Ray GitHub pagina
  • Ray documentatie: de bestemmingspagina, de installatie instructies
  • Ray tutorials
  • Een research paper beschrijft de Ray-systeem in detail
  • Een research paper beschrijft de flexibele primitieven interne Ray voor diep leren
  • Snel serialisatie met Ray en Apache Pijl
  • RLlib: Schaalbare reinforcement learning met Ray (en dit RLlib research paper)
  • Tune: Efficiënte hyperparameter afstemming met Ray
  • Modin: Versnellen van Panda ‘ s met Ray
  • STROOM: a computational framework using reinforcement learning for traffic control modeling
  • Anyscale: het bedrijf achter Ray

vragen moeten worden gericht aan de Ray Discourse of Ray Slack workspace.

Appendix: het uitvoeren van de Code

om de volledige toepassing uit te voeren, installeert u Ray eerst met pip install ray (of zie de installatie-instructies van Ray). Voer vervolgens de volgende code uit met Python. Het implementeert de parameterserver zoals eerder besproken, maar voegt sharding van de parameters in de werknemers toe. Een uitgebreidere versie van dit voorbeeld als Jupyter notebook vind je hier.

merk op dat dit voorbeeld zich richt op eenvoud en dat er meer kan worden gedaan om deze code te optimaliseren.

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.