Derecho matches Keidar and Shraer’s lower bounds for dynamically uniform agreement: No Paxos protocol can safely deliver messages with fewer "information exchange" steps. But does this matter?
Derecho targets a variety of potential deployments and use cases. A common use would be to replicate state within some kind of "sharded" service -- a big pool of servers but broken into smaller replicated subservices that use state machine replication in subsets of perhaps 2, 3 or 5. A different use case would be for massive replication -- tasks like sharing a VM image, a container, or a machine-learned model over huge numbers of nodes. In those cases the number of nodes might be large enough for asymptotic protocol complexity bounds to start to matter -- Derecho's optimality could be a winning argument. But would an infrastructure management service really stream high rates of VM images, containers, and machine-learned models? I suspect that this could arise in future AI Systems... it wouldn't today.
All of which adds up to an interesting question: if theoretical optimality is kind of a "meh" thing, what efficiency bounds really matter for a system like Derecho? And how close to ideal efficiency can a system like this really come?
To answer this question, let me start by arguing that 99% of Derecho can be ignored. Derecho actually consists of a collection of subsystems: you link your C++ code to one library, but internally, that library has several distinct sets of "moving parts". A first subsystem is concerned with moving bytes: our data plane. The second worries about data persistency and versioning. A third is where we implement the Paxos semantics: Derecho's control plane. In fact it handles more than just Paxos -- Derecho's control plane is a single thread that loops through a set of predicates, testing them one by one and then taking triggered actions for any predicate that turns out to be enabled. A fourth subsystem handles requests that query the distributed state: it runs purely on data that has become stable and is totally lock-free and asynchronous -- the other three subsystems can ignore this one entirely. In fact the other three subsystems are as lock-free and asynchronous as we could manage, too -- this is the whole game when working with high speed hardware, because the hardware is often far faster than the software that manages it. We like to think of the RDMA layer and the NVM storage as two additional concurrent systems, and our way of visualizing Derecho is a bit like imagining a machine with five separate moving parts that interact in a few spots, but are as independent as we could manage.
For steady state performance -- bandwidth and latency -- we can actually ignore everything except the update path and the query path. And as it happens, Derecho's query path is just like any query-intensive read-only subsystem: it uses a ton of hashed indices to approximate one-hop access to objects it needs, and it uses RDMA if that one hop involves somehow fetching data from a remote node, or sending a computational task to that remote node. This leads to fascinating questions, in fact: you want those paths to be lock-free, zero-copy, ideally efficient, etc. But we can set those questions to the side for our purposes here -- results like the one by Keidar and Shraer really are about update rates. And for this, as noted a second ago, almost nothing matters except the data-movement path used by the one subsystem concerned with that role. Let's have a closer look.
For large transfers Derecho uses a tree-based data movement protocol that we call a binomial pipeline. In simple terms, we build a binary tree, and over it, create a flow pattern of point to point block transfers that obtains a high level of internal concurrency, like a two-directional bucket brigade -- we call this a reliable multicast over RDMA, or "RDMC"). Just like in an actual bucket brigade, every node settles into a steady behavior, receiving one bucket of data (a "chunk" of bytes) as it sends some other bucket, more or less simultaneously. The idea is to max-out the RDMA network bandwidth (the hardware simply can't move data more efficiently). The actual data structure creates a hypercube "overlay" (a conceptual routing diagram that lives on our actual network, which allows any-to-any communication) of dimension d, and then wraps d binomial trees over it, and you can read about it in our DSN paper, or in the main Derecho paper.
A binary tree is the best you can hope for when using point-to-point transfers to replicate large, chunked, objects. And indeed, when we measure RDMC, it seems to do as well as one can possibly do on RDMA, given that RDMA lacks a reliable one-to-many chunk transfer protocol. So here we actually do have an ideal mapping of data movement to RDMA primitives.
Unfortunately, RDMC isn't very helpful for data too small to "chunk". If we don't have enough data a binomial tree won't settle into its steady-state bucket brigade mode and we would just see a series of point-to-point copying actions. This is still "optimal" at large-scale, but recall that often we will be replicating in a shard of size two, three or perhaps five. We decided that Derecho needed a second protocol for small multicasts, and Sagar Jha implemented what he calls the SMC protocol.
SMC is very simple. The sender, call it process P, has a window, and a counter. To send a message, P places the data in a free slot in its window (each sender has a different window, so we mean "P's window"), and increments the counter (again, P's counter). When every receiver (call them P, Q and R: this protocol actually loops data back, so P sends to itself as well as to the other shard members) has received the message, the slot is freed and P can reuse it, round-robin. In a shard of size three where all the members send, there would be one instance of this per member: three windows, three counters, three sets of receive counters (one per sender).
SMC is quite efficient with small shards. RDMA has a direct-remote-write feature that we can leverage (RDMC uses a TCP-like feature where the receiver needs to post a buffer before the sender transmits, but this direct write is different: here the receiver declares a region of memory into which the sender can do direct writes, without locking).
Or is it? Here we run into a curious philosophical debate that centers on the proper semantics of Derecho's ordered_send: should an ordered_send be immediate, or delayed for purposes of buffering, like a file I/O stream? Sagar, when he designed this layer, opted for urgency. His reasoning was that if a developer can afford to batch messages and send big RDMC messages that carry thousands of smaller ones, this is exactly what he or she would do. So a developer opting for SMC must be someone who prioritizes immediate sends, and wants the lowest possible latency.
So, assume that ordered_send is required to be "urgent". Let's count the RDMA operations that will be needed to send one small object from P to itself (ordered_send loops back), Q and R. First we need to copy the data from P to Q and R: two RDMA operations, because reliable one-sided RDMA is a one-to-one action. Next P increments its full-slots counter and pushes it too -- the updated counter can't be sent in the same operation that sends the data because RDMA has a memory consistency model under which a single operation that spans different cache-lines only guarantees sequential consistency on a per-cache-line basis, and we wouldn't want P or Q to see the full-slots counter increment without certainty that the data would be visible to them. You need two distinct RDMA operations to be sure of that (each is said to be "memory fenced.") So, two more RDMA operations are required. In our three-member shard, we are up to four RDMA operations per SMC multicast.
But now we need acknowledgements. P can't overwrite the slot until P, Q and R have received the data and looked at it, and to report when this has been completed, the three update their receive counters. These counters need to be mirrored to one-another (for fault-tolerance reasons), so P must send its updated receive counter to Q and R, Q to P and R, and R to P and Q: six more RDMA operations, giving a total of ten. In general with a shard of size N, we will see 2*(N-1) RDMA operations to send the data and count, and N*(N-1) for these receive counter reports, a total of N^2+N-2. Asymptotically, RDMC will dominate because of the N^2 term, but N would need to be much larger than five for this to kick in. At a scale of two to five members, we can think of N as more or less a constant, and so this entire term is like a constant.
So by this argument, sending M messages using SMC with an urgent-send semantic "must" cost us M*(N^2+N-2) RDMA operations. Is this optimal?
Here we run into a hardware issue. If you check the specification for the Connect X4 Mellanox device used in my group's experiments, you'll find that it can transmit 75M RDMA messages per second, and also that it has peak performance of 100Gbps (12.5GB) in each link direction. But if your 75M messages are used to report updates to tiny little 4-byte counters, you haven't used much of the available bandwidth: 75M times 4 bytes is only 300MB/s, and as noted above, the device is is bidirection. Since we are talking about bytes, the bidirectional speed could be as high as 25GB/s with an ideal pattern of transfers. Oops: we're too slow by a factor of 75x!
In our TOCS paper SMC peaks at around 7.5M small messages per second, which bears out this observation. We seem to be leaving a lot of capacity unused. If you think about it, everything centers on the assumption that ordered_send should be as urgent as possible. This is actually limiting performance and for applications that average out at 7.5M SMC messages per second or less, but have bursts that might be much higher, this is even inflating latency (a higher-rate burst will just fill the window and the sender will have to wait for a slot).
Suppose our sender wants fast SMC streaming and low latency, and simply wasn't able to do application-level batching (maybe the application has a few independent subsystems of its own that send SMC messages). Well, everyone is familiar with file I/O streaming and buffering. Why not use the same idea here?
Clearly we could have aggregated a bunch of SMC messages, and then done one RDMA transfer for the entire set of full window slots (it happens that RDMA has a so-called "scatter gather/put feature", and we can use that to transfer precisely the newly full slots even if they wrap around the window). Now one counter update covers the full set. Moreover, the receivers can do "batched" receives, and one counter update would then cover the full batch of receives.
An SMC window might have 1000 sender slots in it, with the cutoff for "small" messages being perhaps 100B. Suppose we run with batches of size 250. We'll have cut the overhead factors dramatically: for 1000 SMC messages in the urgent approach, the existing system would send 1000*10 RDMA messages for the 3-member shard: 10,000 in total. Modified to batch 250 messages at a time, only 40 RDMA operations are needed: a clean 250x improvement. In theory, our 7.5M SMC messages per second performance could then leap to 1.9B/second. But here, predictions break down: With 100 byte payloads, that rate would actually be substantially over the limit we calculated earlier, 25GB/s, which limits us to 250M SMC messages per second. Still, 250M is quite a bit faster than 7.5M and worth trying to achieve.
It might not be trivial to get from here to there, even with batching. Optimizations at these insane data rates often aren't be nearly as simple as a pencil-and-paper calculation might suggest. And there are also those urgency semantics issues to think about: A bursty sender might have some gaps in its sending stream. Were one to occur in the middle of a 250 message batch, we shouldn't leave those SMC messages dangling: some form of automatic flush has to kick in. We should also have an API operation so that a user could explicitly force a flush.
Interestingly, once you start to think about this, you'll realize that in this latency sense, Sagar's original SMC is probably "more optimal" than any batched solution can be. If you have just one very urgent notification to send, not a batch, SMC is already a very low-latency protocol; arguably, given his argument that the API itself dictates that SMC should be an urgent protocol, his solution actually is "ideally efficient." What we see above is that if you question that assumption, you can identify an inefficiency -- not that the protocol as given is inefficient under the assumptions it reflects.
Moral of the story? The good news is that right this second, there should be a way to improve Derecho performance for small messages, if the user is a tiny bit less worried about urgency and would like to enable a batching mode (we can make it a configurable feature). But more broadly, you can see is that although Derecho lives in a world governed in part by theory, in the extreme performance range we target and with the various hardware constraints and properties we need to keep in mind, tiny decisions can sometimes shape performance to a far greater degree.
I happen to be a performance nut (and nobody stays in my group unless they share that quirk). Now that we are aware of this SMC performance issue, which was actually called to our attention by Joe Israelevitz when he compared his Acuerdo protocol over RDMA with our Derecho one for 100B objects and beat us hands-down, we'll certainly tackle it. I've outlined one example of an optimization, but it will certainly turn out that there are others too, and I bet we'll end up with a nice paper on performance, and a substantial speedup, and maybe even some deep insights. But they probably won't be insights about protocol complexity. At the end of the day, Derecho may be quite a bit faster for some cases, and certainly this SMC one will be such a case. Yet the asymptotic optimality of the protocol will not really have been impacted: the system is optimal in that sense today! It just isn't as fast as it probably should be, at least for SMC messages sent in high-rate streams!
Showing posts with label rdma. Show all posts
Showing posts with label rdma. Show all posts
Wednesday, 24 July 2019
Tuesday, 27 November 2018
So what's the story about "disaggregated" cloud computing?
The hardware community has suddenly gone wild over a new idea they call "disaggregated" cloud computing infrastructures. I needed to talk about this in my graduate class, so I've been reading some of the papers and asking around.
If you come at the topic from distributed/cloud computing, as I do, you may have been using disaggregation to refer to a much older trend, namely the "decoupling" of control software from the hardware that performs various data and compute-intensive tasks that would otherwise burden a general purpose processor. And this is definitely a legitimate use of the term, but as it turns out, the architecture folks are focused on a different scenario: for them, disaggregation relates to a new way of building your data center compute nodes in which you group elements with similar functionalities, using some form of micro-controller with minimal capabilities to manage components that handle storage, memory, FPGA devices, GPU, TPU, etc. Recent work on quantum computing uses a disaggregated model too: the quantum device is like an experimental apparatus that a control program carefully configures into a specific state, then "runs", and then collects output from.
The argument is that disaggregation reduces wasted power by supporting a cleaner form of multitenancy. For example, consider DRAM. The “d” stands for dynamic, meaning that power is expended to keep every bit continuously refreshed. This is a costly, heat-intensive activity, and yet your DRAM may not even be fully used (studies suggest that 40-50% would be pretty good). If all the DRAM was in some shared rack, bin-packing could easily give you >95% utilization on the active modules, plus you could power down any unused modules.
So disaggregation as a term really can refer to pretty much any situation in which some resources are controlled from programs running "elsewhere", and where you end up with a distributed application that conceptually is a single thing, but has multiple distinct moving parts, with different subsystems specialized for different roles and often using specialized hardware as part of those roles.
At this point I'm seeing the idea as a spectrum, so perhaps it would make sense to start with the older style of control-plane/data-plane separation, say a few words about the value of such a model, and then we can look more closely at this extreme form and ask how it fits into the picture.
Control/data disaggregation is really pretty common idea and dates back quite far: even the earliest IBM mainframes had dedicated I/O coprocessors to operate disks and tapes, and talked about "I/O channels". I could easily list five or ten other examples that have popped up during the past decade or two: very few devices lack some form of general purpose on-board computer, and we can view any such system as a form of disaggregated hardware. But the one that interests me most is the connection to Mach, at the stage when the project was publishing very actively at SOSP and was run from CMU, with various people heading it: Rick Rashid (who ultimately left to launch Microsoft Research), then Brian Bershad, and then Tom Anderson.
Mach was an amazing system, but what I find fascinating is that it happens to also have anticipated many aspects of this new push into disaggregation. As you perhaps will recall (from all those Mach papers you've read...) the basic idea was to have a single micro-kernel that would host various O/S presentation frameworks: a few versions of Linux, perhaps versions of legacy IBM operating systems, etc. Internally, one of those frameworks consisted of a set of processes sharing DLLs, some acting as servers and others as applications. Memory was organized into segments with read/write/execute permissions, and all the underlying interactions centered on an ultra-fast form of RPC in which a single CPU core could run an application thread in segment A, then briefly suspend that thread and activate a thread context in segment B (perhaps A was an application and B is the file server, for example), run in B for a short period, then return to A. The puzzle was to handle permissions (the file server can see the raw disk, but A shouldn't be allowed to, and conversely, the file server can DMA from a specific set of memory areas in A, but shouldn't be able to scan A's memory for passwords). Then because all of this yielded a really huge address space, Mach ran into page table fragmentation issues that were ultimately solved with a novel software inverted page table. And capabilities were used for the low-level message passing primitives. Really cool stuff!
As you might expect, all of these elements had costs: the messaging layer, the segmentation model, context switching, etc. Mach innovated by optimizing those steps, but keep these kinds of costs in mind, because disaggregation will turn out to run into similar issues.
Which brings us to today! The modern version of the story was triggered by the emergence of RDMA as an option in general purpose data centers. As you'll know if you've followed these postings, I'm an RDMA nut, but it isn't just me. RDMA is one of those rare cases where a technology became very mature in a different setting (namely high-performance computing, where it serves as the main communications backbone for packages like the MPI library, and runs on InfiniBand networks), and yet somehow went mostly unnoticed by the general computing community.... until recently, when people suddenly "discovered" it and went bonkers.
As I've discussed previously, one reason that RDMA matured on Infiniband and yet wasn't used on Ethernet centered on RDMA's seeming need for a special style of credit-based I/O model, in which a sender NIC would only transfer data if the receiver had space waiting to receive the data. It is only recently that the emergence of RoCE allowed RDMA to jump to more standard datacenter environments. Today, we do have RDMA in a relatively stable form within a set of racks sharing a TOR switch, assuming that the TOR switch has full bisection bandwidth. But RDMA isn't yet equally mature across routers, particularly in a COS/Spine model where the core network would often be oversubscribed and hence at risk of congestion. There are several competing schemes for deploying RDMA over RoCE v2 with PPF at data-center-wide scale (DCQCN and TIMELY), but work is still underway to understand how those can be combined with Diffsrv or Enterprise VLAN routing) to avoid unwanted interactions between standard TCP/IP and the RDMA layer. It may be a few years before we see "mature" datacenter-scale deployments in which RDMA runs side-by-side with TCP/IP in a non-disruptive way over RoCE v2 (in fact, by then we may be talking about RoCE v5)! Until then, RDMA remains a bit delicate, and must be used with great care.
So why is RDMA even relevant to disaggregation? There is a positive aspect to the answer, but it comes with a cautionary sidebar. The big win is that RDMA has a simple API visible directly to the end-user program (a model called "qpairs" that focuses on "I/O verbs". These are lock-free, and with the most current hardware, permit reliable DMA data transfers from machine to machine at speeds of up to 200Gbps, and latencies as low as .75us. The technology comes in several forms, all rather similar: Mellanox leads on the pure RDMA model (the company has been acquired and will soon be renamed Xylinx, by the way), while Intel is pushing a variant they call OMNI-Path, and other companies have other innovations. These latencies are 10x to 100x better than what you see with TCP, and the data rates are easily 4x better than the fastest existing datacenter TCP solutions. As RDMA pushes up the performance curve to 400Gbps and beyond, the gaps will get even larger. So RDMA is the coming thing, even it hasn't quite become commonplace today.
RDMA is also reliable in its point-to-point configuration, enabling it to replace TCP in many applications, and also offers a way to support relatively low latency remote memory access with cache-line atomicity. Now, it should probably be underscored that with latencies of .75us at the low end to numbers more like 3us for more common devices, RDMA offers the most NUMA of NUMA memory models, but even so, the technology is very fast compared to anything we had previously.
The cautions are the obvious ones. First, RDMA on RoCE is really guaranteed to offer those numbers only if the endpoints live under a TOR switch that can support full bidirectional communication. Beyond that, we need to traverse a router that might experience congestion, and might even drop packets. In these cases, RDMA is on slightly weaker ground.
A second caution is simply that applications can't really handle long memory-access delays, so this NUMA thing becomes a conceptual barrier to casual styles of programming. You absolutely can't view RDMA data-center memory as a gigantic form of local memory. On the contrary, the developer needs to be acutely aware of potential delays, and hence will need to have full control over memory layout. Today, we lack really easily-used tools for that form of control, so massive RDMA applications are the domain of specialists who have a great deal of arcane hardware insight.
So how does this story relate to disaggregation? A first comment is that RDMA is just one of several new hardware options that force us to take control logic out of the main data path. There are a few other examples: with the next generation of NVRAM storage (like Intel's Optane), you can DMA directly from a video camera into a persistent storage card, and with RDMA, you'll be able to do so even if the video isn't on the same machine as the place you plan to store the data. With FPGA accelerators, we often pursue bump-in-the-wire placements: data streams into a memory unit associated to the FPGA at wire rates, it does something, and then we might not even need to touch the main high-volume stream from general purpose code, at all. So the RDMA story is pointing to a broader lack of abstractions covering a variety of data-path scenarios. Moreover, our second caution expands to a broader statement: these different RDMA-like technologies may each bring different constraints and different best-case use scenarios.
Meanwhile, the disaggregation folks are taking the story even further: they start by arguing that we can reduce the power footprint of rack-scale computing systems if we build processors with minimal per-core memory and treat that memory more like a cache than as a full-scale memory. Because memory runs quite hot but the heat dissipation is a function of the memory size, this can slash the power need and heat generation. Then if the processor didn't really need much memory, we are golden, and if it did, we can start to think about ways to intelligently manage the on-board cache, paging data in and out from remote memories hosted in racks dedicated to memory resources and shared by the processor racks (yes, this raises all sorts of issues of protection, but that's the idea). We end up with racks of processors, racks of memory units, racks of storage, racks of FPGA, etc. Each rack will achieve a much higher density of the corresponding devices, which brings some efficiencies too, and we also potentially have multi-tenancy benefits if some applications are memory-intensive but others need relatively little DRAM, some use FPGA but some don't, etc.
The main issue -- the obvious one -- is latency. To appreciate the point, consider standard NUMA machines. The bottom line, as you'll instantly discover should you ever run into it, is that on a NUMA machine, DRAM is split into a few modules, each supporting a couple of local cores, but interconnected by a bus. The issue is that although a NUMA machine is capable of offering transparent memory sharing across DRAM modules, the costs are wildly different when a thread accesses the closest DRAM than when it reaches across the bus to access a "remote" DRAM module (in quotes because this is a DRAM module on the same motherboard). At the best, you'll see a 2x delay: your local DRAM might run with 65ns memory fetch speeds, but a "remote" access could cost 125ns. These delays will balloon if there are also cache-coherency or locking delays: in such cases the NUMA hardware enforces the consistency or locking model, but it runs backplane protocols to do so, and those are costly. NUMA latencies cause havoc.
Not long ago, researchers at MIT wrote a whole series of papers on optimizing Linux to run at a reasonable speed on NUMA platforms.
The cross-product of RDMA with NUMA-ness makes life even stranger. Even when we consider a single server, an RDMA transfer in or out will run in slow motion if the RDMA NIC happens to be far from the DRAM module the transfer touches. You may even get timeouts, and I wonder if there aren't even cases where it would be faster to just copy the data to the local DRAM first, and then use RDMA purely from and to the memory unit closest to the NIC!
This is why those of us who teach courses related to modern NUMA and OS architectures are forced to stress that writing shared memory multicore code can be a terrible mistake from a performance point of view. At best, you need to take full control: you'll have to pin your threads to a set of cores to some single DRAM unit (this helps: you'll end up with faster code. But... it will be highly architecture-specific and on some other NUMA system, it might perform poorly).
In fact NUMA is probably best viewed as a hardware feature ideal for virtualized systems with standard single-threaded programs (and this is true both for genuine virtualization and for containers). Non-specialists should just avoid the model!
So here we have this new disaggregation trend, pushing for the most extreme form of NUMA-ness imaginable. With a standard Intel server, local DRAM will be accessible with a latency of about 50-75ns. Non-local jumps to 125ns, but RDMA could easily exceed 750ns, and 1500ns might not be unusual even for a nearby node, accessible with just one TOR switch hop. (Optical networking could help, driving this down to perhaps 100ns, but that is still far in the future and involves many assumptions.)
There may be an answer, but it isn't obvious people will like it: we will need a new programming style that systematically separates data flows from control, so that this new style of out of band coding would be easier to pull off. Why a new programming style? Well, today's prevailing style of code centers on a program that "owns" the data and holds it in locally malloc-ed memory: I might write code to read frames of video, then ask my GPU to segment the data -- and the data transits through my DRAM (in fact the GPU would often use my DRAM as its memory source). Similarly for FPGA. In a disaggregated environment, we would give the GPU or the FPGA memory of its own, then wire it directly to the data source, and control all of this from an out of band control program running on a completely different processor. The needed abstractions for that style of computing are simply lacking in most of today's programming languages and systems. You do see elements of the story -- for example, Tensor Flow can be told to run portions of its graph on a designated TPU cluster -- but I would argue that we haven't yet found the right OS and programming language coding styles to make this easy at data-center scale.
Worse, we need to focus on applications that would be inherently latency-tolerant: latency barriers will translate to a slowdown for the end user. To avoid that, we need a way of coding that promotes asynchronous flows and doesn't require a lot of hopping around, RPCs or locking. And I'll simply say that we lack that style of coding now -- we haven't really needed it, and the work on this model hasn't really taken off. So this is a solvable problem, for sure, but it isn't there yet.
Beyond all this, we have the issues that Mach ran into. If we disaggregate, all of those same questions will arise: RPC on the critical path, context switch delays, mismatch of the hardware MMU models with the new virtualized disaggregated process model, permissions, you name it. Today's hardware is nothing like the hardware when Mach was created, and I bet there are all sorts of cool new options. But it won't be trivial to figure them all out.
I have colleagues who work in this area, and I think the early signs are very exciting. It looks entirely plausible that the answers are going to be there, perhaps in five years and certainly in ten. The only issue is that the industry seems to think disaggregation is already happening, and yet those answers simply aren't in hand today.
It seems to me that we also risk an outcome where researchers solve the problem, and yet the intended end-users just don't like the solution. The other side of the Tensor Flow story seems to center on the popularity of just using languages everyone already knows, like Python or Java, as the basis for whatever it is we plan to do. But Python has no real concept of resource locations: Tensor Flow takes Python and bolts on the concept of execution in some specific place, but here we are talking about flows, execution contexts, memory management, you name it. So you run some risk that smart young researchers will demonstrate amazing potential, but that the resulting model won't work for legacy applications (unless a miracle occurs and someone finds a way to start with a popular language like Tensor Flow and "compile" it to the needed abstractions). Can such a thing be done? Perhaps so! But when? That strikes me a puzzle.
So I'll stop here, but I will say that disaggregation seems like a cool and really happening opportunity: definitely one of the next big deals. Researchers are wise to jump in. But people headed into the industry, though, who are likely to be technology users rather than inventors, need to appreciate that it is still too early to speculate about what might be successful, and when, and definitely too early for them to get excited: the bottom line message in the lecture I just gave on this topic!
If you come at the topic from distributed/cloud computing, as I do, you may have been using disaggregation to refer to a much older trend, namely the "decoupling" of control software from the hardware that performs various data and compute-intensive tasks that would otherwise burden a general purpose processor. And this is definitely a legitimate use of the term, but as it turns out, the architecture folks are focused on a different scenario: for them, disaggregation relates to a new way of building your data center compute nodes in which you group elements with similar functionalities, using some form of micro-controller with minimal capabilities to manage components that handle storage, memory, FPGA devices, GPU, TPU, etc. Recent work on quantum computing uses a disaggregated model too: the quantum device is like an experimental apparatus that a control program carefully configures into a specific state, then "runs", and then collects output from.
The argument is that disaggregation reduces wasted power by supporting a cleaner form of multitenancy. For example, consider DRAM. The “d” stands for dynamic, meaning that power is expended to keep every bit continuously refreshed. This is a costly, heat-intensive activity, and yet your DRAM may not even be fully used (studies suggest that 40-50% would be pretty good). If all the DRAM was in some shared rack, bin-packing could easily give you >95% utilization on the active modules, plus you could power down any unused modules.
So disaggregation as a term really can refer to pretty much any situation in which some resources are controlled from programs running "elsewhere", and where you end up with a distributed application that conceptually is a single thing, but has multiple distinct moving parts, with different subsystems specialized for different roles and often using specialized hardware as part of those roles.
At this point I'm seeing the idea as a spectrum, so perhaps it would make sense to start with the older style of control-plane/data-plane separation, say a few words about the value of such a model, and then we can look more closely at this extreme form and ask how it fits into the picture.
Control/data disaggregation is really pretty common idea and dates back quite far: even the earliest IBM mainframes had dedicated I/O coprocessors to operate disks and tapes, and talked about "I/O channels". I could easily list five or ten other examples that have popped up during the past decade or two: very few devices lack some form of general purpose on-board computer, and we can view any such system as a form of disaggregated hardware. But the one that interests me most is the connection to Mach, at the stage when the project was publishing very actively at SOSP and was run from CMU, with various people heading it: Rick Rashid (who ultimately left to launch Microsoft Research), then Brian Bershad, and then Tom Anderson.
Mach was an amazing system, but what I find fascinating is that it happens to also have anticipated many aspects of this new push into disaggregation. As you perhaps will recall (from all those Mach papers you've read...) the basic idea was to have a single micro-kernel that would host various O/S presentation frameworks: a few versions of Linux, perhaps versions of legacy IBM operating systems, etc. Internally, one of those frameworks consisted of a set of processes sharing DLLs, some acting as servers and others as applications. Memory was organized into segments with read/write/execute permissions, and all the underlying interactions centered on an ultra-fast form of RPC in which a single CPU core could run an application thread in segment A, then briefly suspend that thread and activate a thread context in segment B (perhaps A was an application and B is the file server, for example), run in B for a short period, then return to A. The puzzle was to handle permissions (the file server can see the raw disk, but A shouldn't be allowed to, and conversely, the file server can DMA from a specific set of memory areas in A, but shouldn't be able to scan A's memory for passwords). Then because all of this yielded a really huge address space, Mach ran into page table fragmentation issues that were ultimately solved with a novel software inverted page table. And capabilities were used for the low-level message passing primitives. Really cool stuff!
As you might expect, all of these elements had costs: the messaging layer, the segmentation model, context switching, etc. Mach innovated by optimizing those steps, but keep these kinds of costs in mind, because disaggregation will turn out to run into similar issues.
Which brings us to today! The modern version of the story was triggered by the emergence of RDMA as an option in general purpose data centers. As you'll know if you've followed these postings, I'm an RDMA nut, but it isn't just me. RDMA is one of those rare cases where a technology became very mature in a different setting (namely high-performance computing, where it serves as the main communications backbone for packages like the MPI library, and runs on InfiniBand networks), and yet somehow went mostly unnoticed by the general computing community.... until recently, when people suddenly "discovered" it and went bonkers.
As I've discussed previously, one reason that RDMA matured on Infiniband and yet wasn't used on Ethernet centered on RDMA's seeming need for a special style of credit-based I/O model, in which a sender NIC would only transfer data if the receiver had space waiting to receive the data. It is only recently that the emergence of RoCE allowed RDMA to jump to more standard datacenter environments. Today, we do have RDMA in a relatively stable form within a set of racks sharing a TOR switch, assuming that the TOR switch has full bisection bandwidth. But RDMA isn't yet equally mature across routers, particularly in a COS/Spine model where the core network would often be oversubscribed and hence at risk of congestion. There are several competing schemes for deploying RDMA over RoCE v2 with PPF at data-center-wide scale (DCQCN and TIMELY), but work is still underway to understand how those can be combined with Diffsrv or Enterprise VLAN routing) to avoid unwanted interactions between standard TCP/IP and the RDMA layer. It may be a few years before we see "mature" datacenter-scale deployments in which RDMA runs side-by-side with TCP/IP in a non-disruptive way over RoCE v2 (in fact, by then we may be talking about RoCE v5)! Until then, RDMA remains a bit delicate, and must be used with great care.
So why is RDMA even relevant to disaggregation? There is a positive aspect to the answer, but it comes with a cautionary sidebar. The big win is that RDMA has a simple API visible directly to the end-user program (a model called "qpairs" that focuses on "I/O verbs". These are lock-free, and with the most current hardware, permit reliable DMA data transfers from machine to machine at speeds of up to 200Gbps, and latencies as low as .75us. The technology comes in several forms, all rather similar: Mellanox leads on the pure RDMA model (the company has been acquired and will soon be renamed Xylinx, by the way), while Intel is pushing a variant they call OMNI-Path, and other companies have other innovations. These latencies are 10x to 100x better than what you see with TCP, and the data rates are easily 4x better than the fastest existing datacenter TCP solutions. As RDMA pushes up the performance curve to 400Gbps and beyond, the gaps will get even larger. So RDMA is the coming thing, even it hasn't quite become commonplace today.
RDMA is also reliable in its point-to-point configuration, enabling it to replace TCP in many applications, and also offers a way to support relatively low latency remote memory access with cache-line atomicity. Now, it should probably be underscored that with latencies of .75us at the low end to numbers more like 3us for more common devices, RDMA offers the most NUMA of NUMA memory models, but even so, the technology is very fast compared to anything we had previously.
The cautions are the obvious ones. First, RDMA on RoCE is really guaranteed to offer those numbers only if the endpoints live under a TOR switch that can support full bidirectional communication. Beyond that, we need to traverse a router that might experience congestion, and might even drop packets. In these cases, RDMA is on slightly weaker ground.
A second caution is simply that applications can't really handle long memory-access delays, so this NUMA thing becomes a conceptual barrier to casual styles of programming. You absolutely can't view RDMA data-center memory as a gigantic form of local memory. On the contrary, the developer needs to be acutely aware of potential delays, and hence will need to have full control over memory layout. Today, we lack really easily-used tools for that form of control, so massive RDMA applications are the domain of specialists who have a great deal of arcane hardware insight.
So how does this story relate to disaggregation? A first comment is that RDMA is just one of several new hardware options that force us to take control logic out of the main data path. There are a few other examples: with the next generation of NVRAM storage (like Intel's Optane), you can DMA directly from a video camera into a persistent storage card, and with RDMA, you'll be able to do so even if the video isn't on the same machine as the place you plan to store the data. With FPGA accelerators, we often pursue bump-in-the-wire placements: data streams into a memory unit associated to the FPGA at wire rates, it does something, and then we might not even need to touch the main high-volume stream from general purpose code, at all. So the RDMA story is pointing to a broader lack of abstractions covering a variety of data-path scenarios. Moreover, our second caution expands to a broader statement: these different RDMA-like technologies may each bring different constraints and different best-case use scenarios.
Meanwhile, the disaggregation folks are taking the story even further: they start by arguing that we can reduce the power footprint of rack-scale computing systems if we build processors with minimal per-core memory and treat that memory more like a cache than as a full-scale memory. Because memory runs quite hot but the heat dissipation is a function of the memory size, this can slash the power need and heat generation. Then if the processor didn't really need much memory, we are golden, and if it did, we can start to think about ways to intelligently manage the on-board cache, paging data in and out from remote memories hosted in racks dedicated to memory resources and shared by the processor racks (yes, this raises all sorts of issues of protection, but that's the idea). We end up with racks of processors, racks of memory units, racks of storage, racks of FPGA, etc. Each rack will achieve a much higher density of the corresponding devices, which brings some efficiencies too, and we also potentially have multi-tenancy benefits if some applications are memory-intensive but others need relatively little DRAM, some use FPGA but some don't, etc.
The main issue -- the obvious one -- is latency. To appreciate the point, consider standard NUMA machines. The bottom line, as you'll instantly discover should you ever run into it, is that on a NUMA machine, DRAM is split into a few modules, each supporting a couple of local cores, but interconnected by a bus. The issue is that although a NUMA machine is capable of offering transparent memory sharing across DRAM modules, the costs are wildly different when a thread accesses the closest DRAM than when it reaches across the bus to access a "remote" DRAM module (in quotes because this is a DRAM module on the same motherboard). At the best, you'll see a 2x delay: your local DRAM might run with 65ns memory fetch speeds, but a "remote" access could cost 125ns. These delays will balloon if there are also cache-coherency or locking delays: in such cases the NUMA hardware enforces the consistency or locking model, but it runs backplane protocols to do so, and those are costly. NUMA latencies cause havoc.
Not long ago, researchers at MIT wrote a whole series of papers on optimizing Linux to run at a reasonable speed on NUMA platforms.
The cross-product of RDMA with NUMA-ness makes life even stranger. Even when we consider a single server, an RDMA transfer in or out will run in slow motion if the RDMA NIC happens to be far from the DRAM module the transfer touches. You may even get timeouts, and I wonder if there aren't even cases where it would be faster to just copy the data to the local DRAM first, and then use RDMA purely from and to the memory unit closest to the NIC!
This is why those of us who teach courses related to modern NUMA and OS architectures are forced to stress that writing shared memory multicore code can be a terrible mistake from a performance point of view. At best, you need to take full control: you'll have to pin your threads to a set of cores to some single DRAM unit (this helps: you'll end up with faster code. But... it will be highly architecture-specific and on some other NUMA system, it might perform poorly).
In fact NUMA is probably best viewed as a hardware feature ideal for virtualized systems with standard single-threaded programs (and this is true both for genuine virtualization and for containers). Non-specialists should just avoid the model!
So here we have this new disaggregation trend, pushing for the most extreme form of NUMA-ness imaginable. With a standard Intel server, local DRAM will be accessible with a latency of about 50-75ns. Non-local jumps to 125ns, but RDMA could easily exceed 750ns, and 1500ns might not be unusual even for a nearby node, accessible with just one TOR switch hop. (Optical networking could help, driving this down to perhaps 100ns, but that is still far in the future and involves many assumptions.)
There may be an answer, but it isn't obvious people will like it: we will need a new programming style that systematically separates data flows from control, so that this new style of out of band coding would be easier to pull off. Why a new programming style? Well, today's prevailing style of code centers on a program that "owns" the data and holds it in locally malloc-ed memory: I might write code to read frames of video, then ask my GPU to segment the data -- and the data transits through my DRAM (in fact the GPU would often use my DRAM as its memory source). Similarly for FPGA. In a disaggregated environment, we would give the GPU or the FPGA memory of its own, then wire it directly to the data source, and control all of this from an out of band control program running on a completely different processor. The needed abstractions for that style of computing are simply lacking in most of today's programming languages and systems. You do see elements of the story -- for example, Tensor Flow can be told to run portions of its graph on a designated TPU cluster -- but I would argue that we haven't yet found the right OS and programming language coding styles to make this easy at data-center scale.
Worse, we need to focus on applications that would be inherently latency-tolerant: latency barriers will translate to a slowdown for the end user. To avoid that, we need a way of coding that promotes asynchronous flows and doesn't require a lot of hopping around, RPCs or locking. And I'll simply say that we lack that style of coding now -- we haven't really needed it, and the work on this model hasn't really taken off. So this is a solvable problem, for sure, but it isn't there yet.
Beyond all this, we have the issues that Mach ran into. If we disaggregate, all of those same questions will arise: RPC on the critical path, context switch delays, mismatch of the hardware MMU models with the new virtualized disaggregated process model, permissions, you name it. Today's hardware is nothing like the hardware when Mach was created, and I bet there are all sorts of cool new options. But it won't be trivial to figure them all out.
I have colleagues who work in this area, and I think the early signs are very exciting. It looks entirely plausible that the answers are going to be there, perhaps in five years and certainly in ten. The only issue is that the industry seems to think disaggregation is already happening, and yet those answers simply aren't in hand today.
It seems to me that we also risk an outcome where researchers solve the problem, and yet the intended end-users just don't like the solution. The other side of the Tensor Flow story seems to center on the popularity of just using languages everyone already knows, like Python or Java, as the basis for whatever it is we plan to do. But Python has no real concept of resource locations: Tensor Flow takes Python and bolts on the concept of execution in some specific place, but here we are talking about flows, execution contexts, memory management, you name it. So you run some risk that smart young researchers will demonstrate amazing potential, but that the resulting model won't work for legacy applications (unless a miracle occurs and someone finds a way to start with a popular language like Tensor Flow and "compile" it to the needed abstractions). Can such a thing be done? Perhaps so! But when? That strikes me a puzzle.
So I'll stop here, but I will say that disaggregation seems like a cool and really happening opportunity: definitely one of the next big deals. Researchers are wise to jump in. But people headed into the industry, though, who are likely to be technology users rather than inventors, need to appreciate that it is still too early to speculate about what might be successful, and when, and definitely too early for them to get excited: the bottom line message in the lecture I just gave on this topic!
Thursday, 14 June 2018
If RDMA is just 4x faster, will that doom adoption?
I’m staring at our latest Derecho numbers and am thinking about their implications.
With additional tuning, by now Weijia and Sagar have Derecho on LibFabrics over TCP running just 4x slower than Derecho mapped to RDMA on the same NIC. I guess this number makes sense, since on our clusters the memcpy speed was about 3.75GB for uncached objects, while RDMA transfers run at a peak rate of 14GB: just about a 4x improvement. So what we are seeing is that with a memcpy in the critical path from user to kernel, and one more memcpy from receiver kernel up to the user (TCP lives in the kernel), throughout drops to the speed of the copy operation. In Derecho, adequately deep pipelines can absorb this effect. Derecho is far slower if the window size is limited to too small a value.
Latency measurements are hard to carry out accurately, at these speeds, but once we get them, I’m sure we will see that latency is higher with TCP: rising from about 1.5us for small objects by some factor associated with memcpy delay and thread scheduling: LibFabrics has extra threads that RDMA avoids. Weijia’s preliminary results suggest that one-way latency rises by tens of microseconds for small objects and hundreds of microseconds for large ones. But today’s cloud applications live happily with much higher latency due to multitasking and scheduling overheads, so this may not be a primary concern for many users.
Moreover, to the extent that memcpy is the culprit, data center hardware vendors could speed up memcpy if they really set out to do so. They could extend the DRAM itself to do the transfer, and offer that functionality via a special instruction. That would probably double memcpy speeds. But the demand hasn’t been there. One could also modify TCP to do some form of scatter-gather with a DMA operation directly from the user-space object, avoiding the memcpy. Of course this would break the semantics of the standard synchronous TCP send, but you could offer the fast path purely with asynchronous I/O, in which case the semantics wouldn’t need to change.
Derecho is very tolerant of high latency. Systems like Tensor Flow are too, as would be any event-stream system using a queuing service (Kafka, SQS) to interconnect its components. But some applications would care more, namely those dominated by RPC. Are those still common?
Leading to my question: if RDMA only gives us 4x speedup on datacenter networks, and latency increases but only by fractions of a millisecond, will operators adopt the technology, given the complexity of deployment? As you know, if you’ve read this blog, Microsoft and Google are gaining experience with a datacenter RDMA, using DCQCN or TIMELY for congestion control and various tricks to run RDMA on Converged Ethernet (RoCE) with flow isolation. They are succeeding, but finding it fairly hard to pull off. Normally, a technology that is this hard to manage and brings less than a 10x benefit doesn’t make it.
One case for RDMA might be based on CPU loads. TCP will peg a CPU doing all this copying, so with Derecho over TCP we see the typical 12-core NUMA node acting more like an 11-core machine, and maybe even like a 10-core machine since there are other threads involved, too. As the datacenter owner, this 10-15% tax on your compute resources could be a big issue, giving RDMA that magic 10x benefit not in one year, but probably over a four or five year period, considering that it was 4x faster in the first place.
A second point is that not every project has all-star developers to do the tuning. So our 4x may translate to a 20x difference for MPI, or a 25x for Oracle. That would drive towards RDMA adoption after all. What Weijia and Sagar did came down to adjusting the SSTMC window size in Derecho. But you need to figure out that for Derecho in this modem the window size is the dominating factor. Who knows what it would be for MVAPICH (MPI), or Oracle, or Tensor Flow? RDMA takes that puzzle, and that datacenter tax, off the table.
My cards are still on RDMA. But these results over TCP definitely came as a surprise!
With additional tuning, by now Weijia and Sagar have Derecho on LibFabrics over TCP running just 4x slower than Derecho mapped to RDMA on the same NIC. I guess this number makes sense, since on our clusters the memcpy speed was about 3.75GB for uncached objects, while RDMA transfers run at a peak rate of 14GB: just about a 4x improvement. So what we are seeing is that with a memcpy in the critical path from user to kernel, and one more memcpy from receiver kernel up to the user (TCP lives in the kernel), throughout drops to the speed of the copy operation. In Derecho, adequately deep pipelines can absorb this effect. Derecho is far slower if the window size is limited to too small a value.
Latency measurements are hard to carry out accurately, at these speeds, but once we get them, I’m sure we will see that latency is higher with TCP: rising from about 1.5us for small objects by some factor associated with memcpy delay and thread scheduling: LibFabrics has extra threads that RDMA avoids. Weijia’s preliminary results suggest that one-way latency rises by tens of microseconds for small objects and hundreds of microseconds for large ones. But today’s cloud applications live happily with much higher latency due to multitasking and scheduling overheads, so this may not be a primary concern for many users.
Moreover, to the extent that memcpy is the culprit, data center hardware vendors could speed up memcpy if they really set out to do so. They could extend the DRAM itself to do the transfer, and offer that functionality via a special instruction. That would probably double memcpy speeds. But the demand hasn’t been there. One could also modify TCP to do some form of scatter-gather with a DMA operation directly from the user-space object, avoiding the memcpy. Of course this would break the semantics of the standard synchronous TCP send, but you could offer the fast path purely with asynchronous I/O, in which case the semantics wouldn’t need to change.
Derecho is very tolerant of high latency. Systems like Tensor Flow are too, as would be any event-stream system using a queuing service (Kafka, SQS) to interconnect its components. But some applications would care more, namely those dominated by RPC. Are those still common?
Leading to my question: if RDMA only gives us 4x speedup on datacenter networks, and latency increases but only by fractions of a millisecond, will operators adopt the technology, given the complexity of deployment? As you know, if you’ve read this blog, Microsoft and Google are gaining experience with a datacenter RDMA, using DCQCN or TIMELY for congestion control and various tricks to run RDMA on Converged Ethernet (RoCE) with flow isolation. They are succeeding, but finding it fairly hard to pull off. Normally, a technology that is this hard to manage and brings less than a 10x benefit doesn’t make it.
One case for RDMA might be based on CPU loads. TCP will peg a CPU doing all this copying, so with Derecho over TCP we see the typical 12-core NUMA node acting more like an 11-core machine, and maybe even like a 10-core machine since there are other threads involved, too. As the datacenter owner, this 10-15% tax on your compute resources could be a big issue, giving RDMA that magic 10x benefit not in one year, but probably over a four or five year period, considering that it was 4x faster in the first place.
A second point is that not every project has all-star developers to do the tuning. So our 4x may translate to a 20x difference for MPI, or a 25x for Oracle. That would drive towards RDMA adoption after all. What Weijia and Sagar did came down to adjusting the SSTMC window size in Derecho. But you need to figure out that for Derecho in this modem the window size is the dominating factor. Who knows what it would be for MVAPICH (MPI), or Oracle, or Tensor Flow? RDMA takes that puzzle, and that datacenter tax, off the table.
My cards are still on RDMA. But these results over TCP definitely came as a surprise!
Monday, 28 May 2018
Derecho on LibFabrics versus Derecho on RDMA: Hot off the wire...
A while back, I mentioned that we were trying to port Derecho to also run over LibFabrics, so that people could use the system on a TCP-only network, or one with the Intel OMNI-Path/IODirect technology, which are based on the LibFabrics API rather than using RDMA Verbs.
So this is starting to work now and I thought I might share a quick summary of the experience! A big thanks to Weijia Song and Sagar Jha, who worked with Cornell ECE undergraduate Alex Katz to make this happen. It was, as it turned out, remarkably hard.
For those lacking context, let me start with a summary of why this topic is of interest, but then that group of people may want to tune out because I'll go back to being highly technical. As you may know, RDMA is a technology for permitting one computer in a data-center or cluster (close-by, densely packed machines) to do direct memory-to-memory data transfers. RDMA comes in various modes: you can do messaging over RDMA (one machine sends, the other receives), and in this case it will behave much like TCP, waiting to send until the receiver is ready, then transmitting losslessly. The big win is that the transfer will run at DMA speeds, which are extremely high: 100Gbps or more. In contrast, if you code a little TCP-based transfer on the identical computers, same network card, you tend to see performance 1/5th what RDMA can achieve or less, because of all the copying (from user space to kernel, then the kernel to kernel transfer over the network in IP packets, then copying up). Copying takes time, and this ends up being 4/5ths of the total path. RDMA eliminates all of that, at least for large transfer.
For small transfers, people work with "one-sided" RDMA in which the sender and receiver prenegotiate a connection but also share a memory region: B grants A permission to read or write within some chunk of B's local memory. Then A basically ends up thinking of B's memory as mapped into A's own computer, although the data transfer isn't as transparent as just reaching into a mapped memory -- it has to occur via special read and write commands. Still, the model would be one of shared memory, reliably updated or read remotely.
RDMA originated on InfiniBand (IB) networks, popular in today's supercomputer systems. Most supercomputer communication runs over a library called the Message Passing Interface, MPI, via an implementation like MVAPICH, and versions like that are highly tuned to leverage RDMA on IB. Our work on the Cornell Derecho system uses this same technology.
Now, continuing the back story, RDMA in this form dates to work done long ago at Cornell by Thorsten Von Eicken (went on to lead GoToMyPC.com) and Werner Vogels (now CTO at Amazon). RDMA took off in industry, and some think it killed off the older style of parallel supercomputing, replacing it with less costly clusters of commodity machines connected with RDMA networks on IB. Anyhow, right from the start the leaders pushed for a TCP-like model. In fact you actually start by creating a TCP connection, a normal one, then put an RDMA connection in place "next to it", using TCP for passing control messages until the RDMA layer is up and running. RDMA itself involves a firmware program that runs in the NIC (so these NICs are like little co-processors, and in fact they often have a full Linux O/S on them, and are coded in C or C++). The interaction between end-host and NIC is through shared "queue" data structures, which are always grouped: there is a queue used for send/receive/read/write operations (called "verbs" for reasons lost in the mists of time), and then a separate completion queue where the NIC reports on operations that have finished.
Verbs, the RDMA API, define a huge number of specialization options. Data can be "inline" (inside the operation) or external (via a pointer, and a length), or one can specify a vector of locations (scatter-gather). Operations can be selected for completion reporting. There is a way to multiplex and demultiplex more than one logical connection over a single RDMA connection, using "keys". There are "tags" that can carry an additional few bytes of information such as object length data (useful in cases where a big transfer is broken down into little sub-transfers).
Then there are ways to use RDMA verbs for unreliable datagram-like communication. Unlike the normal case, where the sender will be certain that messages got through, in order, reliably, with unreliable datagrams some form of end-to-end acknowledgement and retransmission would be needed in the application. And this mode also includes an unreliable multicast feature.
RDMA is a troublesome technology in normal optical ethernet clusters and data centers, and many customers just run it on a second side-by-side IB network to avoid the hassle. But there is an RDMA on ethernet standard called RoCE, and slowly the industry is learning to deploy it without destabilizing normal TCP/IP traffic that the same network would presumably carry. RoCE hasn't been trivial to use in this way: one reads about storms of "priority pause frames" (PPFs), and there are at least two flow control concepts (DCQCN and TIMELY), both in active use, but neither fully mature. Microsoft has just started to run RoCE+DCQCN on its big Azure clusters, although the company is limiting use of RDMA to just its own internal infrastructure tools. Google uses it too. In contrast, any end-user application on an HPC system depends on RDMA via MPI (Azure HPC permits this too). So there are ways to access RDMA, but not directly, on most platforms. Direct use is limited to people who build new infrastructure tools, like we did with our Derecho work.
Against this backdrop, there is a question of who will win in the RoCE market. Intel seemed likely to become a big player when they purchased QLogic, and Mellanox, the dominate company on the HPC side, is the obvious incumbent, with maybe 80% of market share.
But RDMA has technical limits that worry some companies. One concern is the Verbs API itself, which is sort of weird, since it requires these helper TCP connections (you won't find this documented in any clear way, but I challenge you to use RDMA Verbs without having an n * n array of TCP connections handy... CMU seems to have done this in their HeRD/FaSST system, but I'm not aware of any other project that pulled it off). A second is that every RDMA transfer actually occurs as a parallel transfer of some number of "lanes" of data. Each lane is a pair of single-bit connections, one for data travelling in each direction, and at the high-end of the range, lanes typically run at speeds of 14Gbps. Thus when you read that the Connect-X4 from Mellanox runs at 100Gbp/s, you can assume that they employ 7 or 8 lanes to do this. In fact the rates are quoted as one-way rates so you should double them in the case of Derecho, which is aggressive about using connections in a full bidirectional way. By scaling the number of lanes, the industry is now starting to deploy 200Gbps solutions with 400 within sight and 1Tbps expected by 2025 or so.
Now, at these rates it isn't efficient to send a single bit at a time, so instead, RDMA devices normally send frames of data, generally 84 bytes (this is the frame size for 100GE). Thus if you have 8 lanes, a single RDMA transfer might actually carry 512 bytes, with 1024 or more likely by the time the technology reaches the higher rates just mentioned.
The issue is that not every application wants to move objects in blocks of such large size. After all, with direct RDMA writes, a typical operation might access just a few bytes or a word: perhaps 32 or 64 bits. This will be incredibly inefficient over RDMA.
In Derecho we work around that by designing the system around a style that we think of as "steady flow". We want a stream of updates to transit any given path, never pausing even briefly, because we want ways to aggregate traffic. You can read about how we do this in our paper (it was under review by TOCS, but now we are revising it for resubmission, so the version I pointed to is going to change).
Intel has led a group of vendors arguing that this entire direction is ultimately unworkable: we will get to 1Tbps RDMA this way (and Derecho will let you access that speed), but most applications will find that they get a tiny fraction of the full performance because of patterns of transfers that send entire RDMA frames just to read or write a byte or two at a time -- in such cases the majority of the RDMA transfer is just wasted, because the NICs are exchanging perhaps 8 or 16 bytes of useful information and yet every RDMA transfer is of full size: 512 or 1024 bytes.
One answer is for everyone to use Derecho. But LibFabrics, which is Intel's story, aims at a different concept: they want more flexibility about how the hardware could multiplex large numbers of concurrent remote I/O operations so that these huge frames can carry much more useful traffic.
At the same time, LibFabrics breaks with the RDMA Verbs model and tries to more explicitly mimic the normal Linux sockets API. One can love or hate sockets, but at least they are a widely adopted standard that all of us know how to work with. Lots of software runs through TCP or UDP over sockets, hence all of that software can (with some effort) also run on LibFabrics. Yet RDMA is still available as a LibFabrics mapping: there is a way to run directly on Mellanox and theoretically, it maps to the identical RDMA Verbs we would have used in the first place.
So this is starting to work now and I thought I might share a quick summary of the experience! A big thanks to Weijia Song and Sagar Jha, who worked with Cornell ECE undergraduate Alex Katz to make this happen. It was, as it turned out, remarkably hard.
For those lacking context, let me start with a summary of why this topic is of interest, but then that group of people may want to tune out because I'll go back to being highly technical. As you may know, RDMA is a technology for permitting one computer in a data-center or cluster (close-by, densely packed machines) to do direct memory-to-memory data transfers. RDMA comes in various modes: you can do messaging over RDMA (one machine sends, the other receives), and in this case it will behave much like TCP, waiting to send until the receiver is ready, then transmitting losslessly. The big win is that the transfer will run at DMA speeds, which are extremely high: 100Gbps or more. In contrast, if you code a little TCP-based transfer on the identical computers, same network card, you tend to see performance 1/5th what RDMA can achieve or less, because of all the copying (from user space to kernel, then the kernel to kernel transfer over the network in IP packets, then copying up). Copying takes time, and this ends up being 4/5ths of the total path. RDMA eliminates all of that, at least for large transfer.
For small transfers, people work with "one-sided" RDMA in which the sender and receiver prenegotiate a connection but also share a memory region: B grants A permission to read or write within some chunk of B's local memory. Then A basically ends up thinking of B's memory as mapped into A's own computer, although the data transfer isn't as transparent as just reaching into a mapped memory -- it has to occur via special read and write commands. Still, the model would be one of shared memory, reliably updated or read remotely.
RDMA originated on InfiniBand (IB) networks, popular in today's supercomputer systems. Most supercomputer communication runs over a library called the Message Passing Interface, MPI, via an implementation like MVAPICH, and versions like that are highly tuned to leverage RDMA on IB. Our work on the Cornell Derecho system uses this same technology.
Now, continuing the back story, RDMA in this form dates to work done long ago at Cornell by Thorsten Von Eicken (went on to lead GoToMyPC.com) and Werner Vogels (now CTO at Amazon). RDMA took off in industry, and some think it killed off the older style of parallel supercomputing, replacing it with less costly clusters of commodity machines connected with RDMA networks on IB. Anyhow, right from the start the leaders pushed for a TCP-like model. In fact you actually start by creating a TCP connection, a normal one, then put an RDMA connection in place "next to it", using TCP for passing control messages until the RDMA layer is up and running. RDMA itself involves a firmware program that runs in the NIC (so these NICs are like little co-processors, and in fact they often have a full Linux O/S on them, and are coded in C or C++). The interaction between end-host and NIC is through shared "queue" data structures, which are always grouped: there is a queue used for send/receive/read/write operations (called "verbs" for reasons lost in the mists of time), and then a separate completion queue where the NIC reports on operations that have finished.
Verbs, the RDMA API, define a huge number of specialization options. Data can be "inline" (inside the operation) or external (via a pointer, and a length), or one can specify a vector of locations (scatter-gather). Operations can be selected for completion reporting. There is a way to multiplex and demultiplex more than one logical connection over a single RDMA connection, using "keys". There are "tags" that can carry an additional few bytes of information such as object length data (useful in cases where a big transfer is broken down into little sub-transfers).
Then there are ways to use RDMA verbs for unreliable datagram-like communication. Unlike the normal case, where the sender will be certain that messages got through, in order, reliably, with unreliable datagrams some form of end-to-end acknowledgement and retransmission would be needed in the application. And this mode also includes an unreliable multicast feature.
RDMA is a troublesome technology in normal optical ethernet clusters and data centers, and many customers just run it on a second side-by-side IB network to avoid the hassle. But there is an RDMA on ethernet standard called RoCE, and slowly the industry is learning to deploy it without destabilizing normal TCP/IP traffic that the same network would presumably carry. RoCE hasn't been trivial to use in this way: one reads about storms of "priority pause frames" (PPFs), and there are at least two flow control concepts (DCQCN and TIMELY), both in active use, but neither fully mature. Microsoft has just started to run RoCE+DCQCN on its big Azure clusters, although the company is limiting use of RDMA to just its own internal infrastructure tools. Google uses it too. In contrast, any end-user application on an HPC system depends on RDMA via MPI (Azure HPC permits this too). So there are ways to access RDMA, but not directly, on most platforms. Direct use is limited to people who build new infrastructure tools, like we did with our Derecho work.
Against this backdrop, there is a question of who will win in the RoCE market. Intel seemed likely to become a big player when they purchased QLogic, and Mellanox, the dominate company on the HPC side, is the obvious incumbent, with maybe 80% of market share.
But RDMA has technical limits that worry some companies. One concern is the Verbs API itself, which is sort of weird, since it requires these helper TCP connections (you won't find this documented in any clear way, but I challenge you to use RDMA Verbs without having an n * n array of TCP connections handy... CMU seems to have done this in their HeRD/FaSST system, but I'm not aware of any other project that pulled it off). A second is that every RDMA transfer actually occurs as a parallel transfer of some number of "lanes" of data. Each lane is a pair of single-bit connections, one for data travelling in each direction, and at the high-end of the range, lanes typically run at speeds of 14Gbps. Thus when you read that the Connect-X4 from Mellanox runs at 100Gbp/s, you can assume that they employ 7 or 8 lanes to do this. In fact the rates are quoted as one-way rates so you should double them in the case of Derecho, which is aggressive about using connections in a full bidirectional way. By scaling the number of lanes, the industry is now starting to deploy 200Gbps solutions with 400 within sight and 1Tbps expected by 2025 or so.
Now, at these rates it isn't efficient to send a single bit at a time, so instead, RDMA devices normally send frames of data, generally 84 bytes (this is the frame size for 100GE). Thus if you have 8 lanes, a single RDMA transfer might actually carry 512 bytes, with 1024 or more likely by the time the technology reaches the higher rates just mentioned.
The issue is that not every application wants to move objects in blocks of such large size. After all, with direct RDMA writes, a typical operation might access just a few bytes or a word: perhaps 32 or 64 bits. This will be incredibly inefficient over RDMA.
In Derecho we work around that by designing the system around a style that we think of as "steady flow". We want a stream of updates to transit any given path, never pausing even briefly, because we want ways to aggregate traffic. You can read about how we do this in our paper (it was under review by TOCS, but now we are revising it for resubmission, so the version I pointed to is going to change).
Intel has led a group of vendors arguing that this entire direction is ultimately unworkable: we will get to 1Tbps RDMA this way (and Derecho will let you access that speed), but most applications will find that they get a tiny fraction of the full performance because of patterns of transfers that send entire RDMA frames just to read or write a byte or two at a time -- in such cases the majority of the RDMA transfer is just wasted, because the NICs are exchanging perhaps 8 or 16 bytes of useful information and yet every RDMA transfer is of full size: 512 or 1024 bytes.
One answer is for everyone to use Derecho. But LibFabrics, which is Intel's story, aims at a different concept: they want more flexibility about how the hardware could multiplex large numbers of concurrent remote I/O operations so that these huge frames can carry much more useful traffic.
At the same time, LibFabrics breaks with the RDMA Verbs model and tries to more explicitly mimic the normal Linux sockets API. One can love or hate sockets, but at least they are a widely adopted standard that all of us know how to work with. Lots of software runs through TCP or UDP over sockets, hence all of that software can (with some effort) also run on LibFabrics. Yet RDMA is still available as a LibFabrics mapping: there is a way to run directly on Mellanox and theoretically, it maps to the identical RDMA Verbs we would have used in the first place.
So with this in mind, we bit the bullet and ported Derecho to LibFabrics. Now our main software distribution actually will have both options, and we'll use some form of configuration manager (we're thinking about Getopt or its sibling, the slightly fancier Getpot). Then you'll be able to tell us which NIC to select, which mode to run in, etc.
Derecho it looking pretty good on LibFabrics right now. We're seeing identical performance for RDMA versus LibFabrics (on the identical NIC and network, obviously), provided that the transfer size is large. For small operations, LibFabrics seems slower. This is clearly at odds with a direct mapping to RDMA verbs (otherwise we would have seen identical performance for this case too), so we'll need to understand the root cause more deeply. We've also tested Derecho over LibFabrics mapped to TCP, still on the same network but using the kernel stack, and it seems to be about 4x slower than with RDMA, again in the large objects case. Derecho over TCP with small objects is very slow, so there is definitely a serious puzzle there.
One very cool option will be to look at Derecho on WAN links over TCP. RDMA can't run on a WAN network, but we definitely can run LibFabrics this way.
Summary: work in progress, but work revealing very nice progress, even if some mysteries remain to be resolved. Watch this blog for updates! I'm sure we'll have lots of them in months to come.
(Added May 30): Here's data from an experiment run by Weijia Song, Alex Katz and Sagar Jha for a 3-member Derecho shard or group, first with 1 sender and all three members receiving and then with all sending and all receiving, using our atomic multicast configuration of ordered_send (compare with Zookeeper's ZAB protocol, without checkpointing).
What you see here is that (1) LibFabrics didn't introduce overhead when we map down to RDMA. To see this compare Derecho ROCE and IB against the Derecho Baseline (which used Verbs directly). So, two left data sets versus the one on the right. Axis is in gigabytes-per-second and the color coding is for the message size: 100MB, 1MB and 10KB.
Next look at the middle three cases. These were ones in which we used the same NICs but told LibFabrics not to use RDMA and instead to run on the native TCP for those NICs (TCP works perfectly well on these NICs, but doesn't leverage RDMA). So of course performance drops, by roughly the factor of 4x mentioned above, but what is impressive is that if you were to go to our Derecho paper and compare this with Zookeeper or LibPaxos, we are still close to 100x faster than those libraries! That would be a true apples-to-apples comparison, since ZAB and LibPaxos run on TCP or UDP, not RDMA, so when we compared Derecho against them previously, it was a bit unfair to them -- they had no way to leverage RDMA.
Why is Derecho so much faster than classic Paxos? Clearly the world already had reached a data rate in which streaming data and doing receiver-side batching is far preferable to the classic 2-phase commit for each action. Nobody had noticed this, but Derecho happens to live in this new configuration because our development methodology led us to that formulation of the protocols. And here we can see that it pays off even on a TCP infrastructure!
Sorry for all the explanation points, but after something like 35 years of working on this kind of thing, I'm thrilled to see these numbers and to realize what a great opportunity this represents.
Wednesday, 7 March 2018
Data stream computing
I've actually posted on this topic in the past, but I spend so much of my own time thinking about it that I'm going to revisit the question from my "revised and improved" perspective, a year or so down the road.
Context: with the move towards a disaggregated data center model in which we use RDMA or other forms of next-generation direct access to talk to remote memory (perhaps persistent, perhaps not), we find ourselves in a world where the underlying costs and barriers have shifted dramatically relative to the programming style familiar in the past.
Specific example: Consider 2-phase commit, or your favorite consensus protocol, or Paxos. In the recent past, we would program these protocols by having some leader who initiates the protocol and sends out a request to the other participants: "can you commit transaction 71?" or "I vote 1", or "I propose that we place value v into Paxos log slot 22, and this is my 3rd ballot for that slot." Responses eventually come back, and after a round or two of these back-and-forth interactions, the protocol terminates.
In that classic way of thinking, there was a kind of implicit balance in mind between the cost of moving the data (value v in the example above) and the cost of the back-and-forth round-trips. I'm not quite sure how to best express this sense of balance, but what one finds is that the cost of the round-trip actions (the RTT, as we say in the business...) is sort of "reasonable" relative to the bandwidth available for moving the value field, often over TCP connections or UDP.
Today, with new forms of direct remote memory access, talking to remote memory over a technology like RDMA is actually faster than talking to local memory, but only in the sense that RDMA can sustain a far higher bandwidth than local actions like using memcpy (the fastest available copying primitive on a Linux/C computing platform) to move data from one place in memory to another, assuming that the data in question isn't in the L2 cache. As RDMA speeds up, this gap will only get larger. So it is very cheap to move data from machine A to machine B.
In contrast, the RTT for a modern optical Ethernet is surprisingly high, when you consider quite how fast copying can be. We see RTTs in the 1.5us to 2.5us range: quite fast compared to the 1-10ms numbers that were common for protocols running over TCP/UDP/IP, but relatively sluggish if you consider the number of bytes that could have been sent in that time, particularly if you add in the delays for scheduling a thread to notice the request coming in (when A's message arrives on B), or to send the reply (when B's response reaches A).
If A blocks sending while waiting for this RTT to complete, quite a few bytes won't be sent. And as RDMA gets faster (today, 100Gbps, but tomorrow 200, then 400, and 1Tbps is within range now), the amount of missed transmission opportunity gets pretty substantial.
Concurrency feels like the obvious answer, but this instinctive reaction proves to be naive. The theory would be that if A has lots of side by side transactions with B, then while one waits, another can transmit. But that overlooks overheads: concurrency also brings many kinds of costs, and this model is anything but a clear win! Those costs could quickly add up: locking to ensure that the transfers won't interfere with one-another, memory contention on the DRAM chunks where the data lives, various forms of state that might be sitting around while the round-trip interactions are running (threads consume stack space, for example). So concurrency doesn't come for free.
Batching is a second possibility: A could collect a bunch of requests, then send them as a batch (while collecting the next batch), B could respond on the whole series of requests (one by one, but as a batch of responses), and so forth. This amortizes costs in a nice way.
Batching makes sense on a receiver, too. Rather than sending batches and forcing the receiver to use those batch sizes, a sender could send continuously, and the receiver could bite off a chunk of incoming records based on when it happens to be ready to run. So if we have A sending continuously, rather than having A batch 10 items at a time, it could stream steadily to B. B might be ready for its next chunk of input at a moment when there are 11 items available; it treats these as a batch of 11. Then at the next loop, B is perhaps ready for input when 4 new items have turned up: a batch of 4. We still see a benefit of amortized costs, but the batch sizes are variable and determined by when B happens to be ready, rather than fixed and decided by A (the sender).
Derecho works this way.
Now why are we discussing these obvious points? Well, the optimality of Derecho is directly tied to its use of this style of receiver-side batching. The key "thing" about Derecho is that it runs a version of Paxos modified to make decisions as soon as possible, based on the Paxos notion of safety, using receiver-side batches. This allows us to stream an exceptionally high rate of Paxos requests, process them with no unnecessary delays, and amortize all costs over batches of events.
In fact, the value of this method centers on the steady stream of updates. With one update, by itself, classic Paxos is a reasonable choice of protocol. But with a stream of updates, we need to amortize costs for efficiency. The classic protocols run in a greedy way, and cease to be efficient because they miss this opportunity!
So now the question arises: is this a story purely about Derecho, or does the same opportunity transition to other kinds of systems that aren't doing atomic multicast (vertical Paxos) and atomic log updates (classic durable Paxos)? For example, could a distributed file system somehow gain performance by being implemented to use the same sort of pattern? Could a database system be optimized by leveraging this sort of transformation?
And we can pose the problem even more broadly. As a programming question (almost a compilation question), is there a systematic programming methodology here, one that would lead the developer to an optimized solution matched to the underlying cost model mentioned earlier (the cost model in which steady flow works extremely well at high rates and with large data volumes, but RTT looks somewhat costly)? How could one start with a specification of a file system, or a specification of Paxos, and systematically arrive at a solution like Derecho?
I find it fascinating that despite all the work that has been done on stream processing in database systems, there seems to be very little prior work on the kind of protocol optimization I've outlined. The underlying "memory model" is really just an exaggerated NUMA one, with a cache-line memory coherence model, remote memory access, but with unusually high latencies relative to the extremely high bandwidth. By and large, my colleagues in the PL community view the resulting questions as being variations on what they are already used to: they have extensive experience with NUMA programming. Yet here we can see that we actually are after solutions that can be quite different from the classic ones: Derecho doesn't look a lot like Paxos at first glance, and the optimality we achieved emerges from the Paxos protocol transformations that let us optimize for the RDMA environment. So there was something non-trivial happening here, even though it happens over the standard NUMA model.
I don't know if we have PL readers of this blog, but I would love to hear their thoughts, if so!
Context: with the move towards a disaggregated data center model in which we use RDMA or other forms of next-generation direct access to talk to remote memory (perhaps persistent, perhaps not), we find ourselves in a world where the underlying costs and barriers have shifted dramatically relative to the programming style familiar in the past.
Specific example: Consider 2-phase commit, or your favorite consensus protocol, or Paxos. In the recent past, we would program these protocols by having some leader who initiates the protocol and sends out a request to the other participants: "can you commit transaction 71?" or "I vote 1", or "I propose that we place value v into Paxos log slot 22, and this is my 3rd ballot for that slot." Responses eventually come back, and after a round or two of these back-and-forth interactions, the protocol terminates.
In that classic way of thinking, there was a kind of implicit balance in mind between the cost of moving the data (value v in the example above) and the cost of the back-and-forth round-trips. I'm not quite sure how to best express this sense of balance, but what one finds is that the cost of the round-trip actions (the RTT, as we say in the business...) is sort of "reasonable" relative to the bandwidth available for moving the value field, often over TCP connections or UDP.
Today, with new forms of direct remote memory access, talking to remote memory over a technology like RDMA is actually faster than talking to local memory, but only in the sense that RDMA can sustain a far higher bandwidth than local actions like using memcpy (the fastest available copying primitive on a Linux/C computing platform) to move data from one place in memory to another, assuming that the data in question isn't in the L2 cache. As RDMA speeds up, this gap will only get larger. So it is very cheap to move data from machine A to machine B.
In contrast, the RTT for a modern optical Ethernet is surprisingly high, when you consider quite how fast copying can be. We see RTTs in the 1.5us to 2.5us range: quite fast compared to the 1-10ms numbers that were common for protocols running over TCP/UDP/IP, but relatively sluggish if you consider the number of bytes that could have been sent in that time, particularly if you add in the delays for scheduling a thread to notice the request coming in (when A's message arrives on B), or to send the reply (when B's response reaches A).
If A blocks sending while waiting for this RTT to complete, quite a few bytes won't be sent. And as RDMA gets faster (today, 100Gbps, but tomorrow 200, then 400, and 1Tbps is within range now), the amount of missed transmission opportunity gets pretty substantial.
Concurrency feels like the obvious answer, but this instinctive reaction proves to be naive. The theory would be that if A has lots of side by side transactions with B, then while one waits, another can transmit. But that overlooks overheads: concurrency also brings many kinds of costs, and this model is anything but a clear win! Those costs could quickly add up: locking to ensure that the transfers won't interfere with one-another, memory contention on the DRAM chunks where the data lives, various forms of state that might be sitting around while the round-trip interactions are running (threads consume stack space, for example). So concurrency doesn't come for free.
Batching is a second possibility: A could collect a bunch of requests, then send them as a batch (while collecting the next batch), B could respond on the whole series of requests (one by one, but as a batch of responses), and so forth. This amortizes costs in a nice way.
Batching makes sense on a receiver, too. Rather than sending batches and forcing the receiver to use those batch sizes, a sender could send continuously, and the receiver could bite off a chunk of incoming records based on when it happens to be ready to run. So if we have A sending continuously, rather than having A batch 10 items at a time, it could stream steadily to B. B might be ready for its next chunk of input at a moment when there are 11 items available; it treats these as a batch of 11. Then at the next loop, B is perhaps ready for input when 4 new items have turned up: a batch of 4. We still see a benefit of amortized costs, but the batch sizes are variable and determined by when B happens to be ready, rather than fixed and decided by A (the sender).
Derecho works this way.
Now why are we discussing these obvious points? Well, the optimality of Derecho is directly tied to its use of this style of receiver-side batching. The key "thing" about Derecho is that it runs a version of Paxos modified to make decisions as soon as possible, based on the Paxos notion of safety, using receiver-side batches. This allows us to stream an exceptionally high rate of Paxos requests, process them with no unnecessary delays, and amortize all costs over batches of events.
In fact, the value of this method centers on the steady stream of updates. With one update, by itself, classic Paxos is a reasonable choice of protocol. But with a stream of updates, we need to amortize costs for efficiency. The classic protocols run in a greedy way, and cease to be efficient because they miss this opportunity!
So now the question arises: is this a story purely about Derecho, or does the same opportunity transition to other kinds of systems that aren't doing atomic multicast (vertical Paxos) and atomic log updates (classic durable Paxos)? For example, could a distributed file system somehow gain performance by being implemented to use the same sort of pattern? Could a database system be optimized by leveraging this sort of transformation?
And we can pose the problem even more broadly. As a programming question (almost a compilation question), is there a systematic programming methodology here, one that would lead the developer to an optimized solution matched to the underlying cost model mentioned earlier (the cost model in which steady flow works extremely well at high rates and with large data volumes, but RTT looks somewhat costly)? How could one start with a specification of a file system, or a specification of Paxos, and systematically arrive at a solution like Derecho?
I find it fascinating that despite all the work that has been done on stream processing in database systems, there seems to be very little prior work on the kind of protocol optimization I've outlined. The underlying "memory model" is really just an exaggerated NUMA one, with a cache-line memory coherence model, remote memory access, but with unusually high latencies relative to the extremely high bandwidth. By and large, my colleagues in the PL community view the resulting questions as being variations on what they are already used to: they have extensive experience with NUMA programming. Yet here we can see that we actually are after solutions that can be quite different from the classic ones: Derecho doesn't look a lot like Paxos at first glance, and the optimality we achieved emerges from the Paxos protocol transformations that let us optimize for the RDMA environment. So there was something non-trivial happening here, even though it happens over the standard NUMA model.
I don't know if we have PL readers of this blog, but I would love to hear their thoughts, if so!
Wednesday, 8 March 2017
The ultimate Paxos (and Atomic Multicast) protocol
Many years ago, probably around 1986, Barbara Simons organized a workshop on replication at Asilomar, a California resort that had an iconic role in early systems research (it took a while, but eventually our community was too large to fit there).
Her idea was to bring people together across areas: theory and practice, and within the practitioners, databases as well as other forms of distributed systems. It was a good idea, and a great workshop.
In Jim Gray's talk, he pointed out that the interaction pattern we associate with the 2-phase commit protocol was seemingly universal, and that perhaps we were wrong to think of 2-phase commit as primarily a database construct. Instead, he then asked, if 2-phase commit is really concerned with something deeper than database transactions, what is this deeper core concept? The essential point of his talk was that the 2-phase pattern seen in 2PC clearly allowed a distributed system to "learn" something. And from this, he suggested, that if we could start to appreciate the minimal "knowledge" required for a distributed system to be correct, we could build a minimal implementation of that protocol and solve the problem once and for all.
A long time has passed. Jim is no longer with us, and we know all about knowledge in distributed systems, and how processes learn. Even so, Jim's question still sometimes comes up. I mentioned this to Idit Keidar today over lunch, and her response was definitive: she convinced me that today, we really do (finally) understand the answer to Jim's question. Her thinking centers on work she published in 2006 with Alex Shraer.
Here's what she explained.
First, she observed, distributed computing is ultimately about just one question: fault-tolerant consensus. For her, Jim had noticed this, but was understanding it as something about the 2PC communication pattern rather than appreciating that the thing that matters more is consensus: moving from a state in which some decision is uncertain to one in which a decision has been reached. As Idit views the question, one can transform consensus into other forms, we can route the messages in all sorts of patterns, but the bottom line is that either we achieve agreement via consensus or we simply aren't building systems that can make logically sound claims about their behavior.
Next, she pointed out, agreement is trivial while failures aren't happening. While a system remains stable, the author of a new piece of information simply needs to multicast it, and this accomplishes consensus. If there might be many authors, you can circulate a token around them either before they send (as in the old Totem and Transis protocols) or after the messages arrive, to assign them a delivery ordering.
And so in Idit's view, the only hard issue is to handle failures. Obviously, in the case of 2PC, particularly back in 1986, the field started out with a somewhat muddled understanding of this aspect: 2PC starts by stating that there is a set of processes that need to achieve agreement, but where does that set come from? In a modern system like Derecho, the set itself is the output of a consensus layer. 2PC uses a crash failure model, but this is one of many models. Back in 1986 people were very focused on models: crash failures, failstop failures, omission to send, omission to receive, timing errors, Byzantine models.
But these days all that really matters is to handle crash failures correctly. Some organizations toy with Byzantine fault-tolerance, but honestly, I've never met anyone who had a service that actually came under a Byzantine attack. Maybe the blockchain people will finally have that experience.
So let's focus on crash failures for a moment. In light of the FLP theorem, we know now that without a perfect failure detector, protocols can't be proved correct: you can show safety, but not liveness. In practice, we solve this by forcing a seemingly faulty process to leave the system and then, if you want, it can rejoin.
So failure becomes a purely behavioral abstraction: if the majority of the system deems some process to be worthy of excluding, for whatever arbitrary reason it desires, than out goes the offending process, end of story.
Where did the majority constraint come from? The role of the majority restriction is to prevent logical partitioning.
So, we end up with a rather dynamic form of membership: the system defines its own membership, excluding processes that seem faulty, and makes progress as long as it can maintain a dynamic form of majority. To whit: at any point in time, some epoch defines the composition of the system. In order to move to a new epoch, the systems needs agreement by the majority of whoever is in the active epoch.
So here's where all of this leads: Derecho is a concrete implementation of this new-age perspective on Jim's question. Indeed, it is the ultimate story in the sense that the system is optimal in many different ways.
To appreciate this, you'll need to read the Derecho papers, but in a nutshell, the system maps consensus onto RDMA hardware in an exceptionally efficient way. But the protocol itself runs consensus on the configuration of each epoch, and then uses a cheaper consensus protocol within an epoch (one that can assume membership is stable and that failures won't occur), leaving a very clean realization of distributed computing.
Indeed, Derecho is a constructive lower bound in every interesting dimension. It is an optimal solution to the problem of distributed computing, using consensus-based methods.
Why do I make this claim? Well, first, during a given epoch, the system is as quick to deliver messages as is possible: one can prove that any system that delivers messages with fewer "exchanges of information" between its processes is either incorrect, or at last at risk of needing to stop because of some single fault.
Next, one can show that Derecho's agreement on the state of each membership epoch is optimal. Here, Derecho makes use of an all-to-all pattern of information exchange, and I asked Idit if she thought the protocol could be improved. Idit pointed again to her 2006 papers with Alex. Without prior knowledge of which processes failed, and how many failed, she explained, this pattern of information exchange is the quickest way to reach agreement on the membership of the next epoch.
Finally, we can show that Derecho makes progress with a failure model called <>P: eventually perfect failure detection. Idit explained to me that in the past, people actually thought it might make sense to focus on progress with weaker detection models, like <>W, but that if you do so, you either end up with a fault model equivalent to <>P, or you end up with slower agreement protocols that look much more like Byzantine agreement. So, for the style of quick progress Derecho is after, she explains, <>P is the right goal. And Derecho is live with <>P, provided that no more than a minority of processes fail in any epoch. Which again, is the best one can do.
Now, Idit is a theory person, but it is interesting for me as a practitioner to also think about practicalities. As the old adage goes: "In theory, theory and practice are the same, but in practice, they differ."
As it happens, Derecho is optimal in a communications-engineering (networking) sense.
Given that reliable networks always have a one-to-one acknowledgement based layer, reliable multicast over a tree is an optimal data dissemination pattern: if you try and disseminate multicasts over an unreliable 1-N protocol, the cost of detecting lost packets and resending them will be very high compared to a tree of unicast transfers. (Perhaps optical networks with optically aggregated acknowledgements could offer a slight hardware speedup, but even this isn't clear, since the optical aggregator would itself be a tree).
Now if you happen to be a cloud computing engineer, and read the above, what will jump to mind is heavy-tailed behaviors and multi-tenancy: Derecho protocols sometimes relay data, so if a relayer is very slow, everyone waits. Paxos classically would avoid this using quorums: the system doesn't wait for the slowest process. So how can I claim that Derecho is optimal in a practical sense if it doesn't use quorums?
There are a few answers. A long-winded one would talk about work Fernando Pedone and his student, Parissa Jallali, did while visiting my group a few years ago. Basically, they studied quorum behaviors in Paxos and discovered that while Paxos can briefly "outrun" a slow process, eventually work piles up and either flow-control causes the protocol to pause, or a shifting pattern of just who is the slow process switches the slow guy into the quorum and some previous quorum member becomes slow. Either way, Paxos basically halts until everyone catches up and is back in sync. So quorum patterns do not evade the disruption caused by heavy tailed behaviors.
Conversely, offloading the protocol into hardware actually can eliminate that issue, because the hardware is dedicated: the network spends 100% of its time communicating, so if you can describe a pattern of communication, then let it rip, the network is the ideal engine for moving data. As it happens, Derecho generates deterministic data transfer schedules, hence given adequately programmable NICs we can hand the entire sequence of block transfers to the NIC. So we can even make "optimal" use of the network, and since a NIC never sleeps or pauses, quorum behaviors aren't needed even if end-applications sometimes are a bit slow.
So a road that for me started around when Jim asked his question about 2PC seems to have reached its end: Derecho implements the ultimate Paxos protocols for atomic multicast (often called vertical Paxos) and for persisted memory (classic Paxos). We could add an optimistic early delivery protocol with a flush, too, as in Isis and Vsync, but we decided to keep the system simple and omitted it: most people who would use that feature probably just want raw RDMC from the Derecho API, and this we do offer.
And so the Paxos problem is solved. And you know what? Its about time! Idit feels that it was solved back in 2006, actually. As for me, well, until I can write an application using the ultimate protocol, the problem is open. But today, I finally can. (I don't mind at all that Derecho employs a protocol that is actually extremely similar to our first Isis protocols from 1985.)
So should we all pack our bags and go home?
Not quite yet. First, there are other forms of distributed consistency, like convergent (gossip) protocols, self-stabilization, and of course, Byzantine Agreement. It would be nice to see how those fit into this picture and whether there can be a single integrated story that combines all the elements.
A second issue is the engineering complexity of modern platforms. I'll write a whole blog posting on this sometime soon, but suffice it to say that in a data center with physical topology (racks, switches, TOR switches, failure-independence domains...), GPU clusters, NetFPGA accelerators, Intel SGX protection enclaves... it just isn't obvious how to write code for such environments. Derecho is just part of the answer, and not the whole story.
Then beyond all of this are dimensions we have yet to tackle in Derecho itself. For example, even if Derecho is the ultimate data center protocol, is it also the ultimate WAN version? As it happens, I suspect that this may be true too, but more attention to the question will be needed. Anyhow, until we have it running, I won't believe the story even if I figure it out "in theory". After all, in theory, theory and practice are the same... but in practice, they are enormously different.
So I wouldn't despair: very likely we are finally at the end of the road for Paxos, but it certainly isn't the end of the road for distributed systems. Watch this space: I can promise plenty of interesting new questions, and new answers, in years to come.
Her idea was to bring people together across areas: theory and practice, and within the practitioners, databases as well as other forms of distributed systems. It was a good idea, and a great workshop.
In Jim Gray's talk, he pointed out that the interaction pattern we associate with the 2-phase commit protocol was seemingly universal, and that perhaps we were wrong to think of 2-phase commit as primarily a database construct. Instead, he then asked, if 2-phase commit is really concerned with something deeper than database transactions, what is this deeper core concept? The essential point of his talk was that the 2-phase pattern seen in 2PC clearly allowed a distributed system to "learn" something. And from this, he suggested, that if we could start to appreciate the minimal "knowledge" required for a distributed system to be correct, we could build a minimal implementation of that protocol and solve the problem once and for all.
A long time has passed. Jim is no longer with us, and we know all about knowledge in distributed systems, and how processes learn. Even so, Jim's question still sometimes comes up. I mentioned this to Idit Keidar today over lunch, and her response was definitive: she convinced me that today, we really do (finally) understand the answer to Jim's question. Her thinking centers on work she published in 2006 with Alex Shraer.
Here's what she explained.
First, she observed, distributed computing is ultimately about just one question: fault-tolerant consensus. For her, Jim had noticed this, but was understanding it as something about the 2PC communication pattern rather than appreciating that the thing that matters more is consensus: moving from a state in which some decision is uncertain to one in which a decision has been reached. As Idit views the question, one can transform consensus into other forms, we can route the messages in all sorts of patterns, but the bottom line is that either we achieve agreement via consensus or we simply aren't building systems that can make logically sound claims about their behavior.
Next, she pointed out, agreement is trivial while failures aren't happening. While a system remains stable, the author of a new piece of information simply needs to multicast it, and this accomplishes consensus. If there might be many authors, you can circulate a token around them either before they send (as in the old Totem and Transis protocols) or after the messages arrive, to assign them a delivery ordering.
And so in Idit's view, the only hard issue is to handle failures. Obviously, in the case of 2PC, particularly back in 1986, the field started out with a somewhat muddled understanding of this aspect: 2PC starts by stating that there is a set of processes that need to achieve agreement, but where does that set come from? In a modern system like Derecho, the set itself is the output of a consensus layer. 2PC uses a crash failure model, but this is one of many models. Back in 1986 people were very focused on models: crash failures, failstop failures, omission to send, omission to receive, timing errors, Byzantine models.
But these days all that really matters is to handle crash failures correctly. Some organizations toy with Byzantine fault-tolerance, but honestly, I've never met anyone who had a service that actually came under a Byzantine attack. Maybe the blockchain people will finally have that experience.
So let's focus on crash failures for a moment. In light of the FLP theorem, we know now that without a perfect failure detector, protocols can't be proved correct: you can show safety, but not liveness. In practice, we solve this by forcing a seemingly faulty process to leave the system and then, if you want, it can rejoin.
So failure becomes a purely behavioral abstraction: if the majority of the system deems some process to be worthy of excluding, for whatever arbitrary reason it desires, than out goes the offending process, end of story.
Where did the majority constraint come from? The role of the majority restriction is to prevent logical partitioning.
So, we end up with a rather dynamic form of membership: the system defines its own membership, excluding processes that seem faulty, and makes progress as long as it can maintain a dynamic form of majority. To whit: at any point in time, some epoch defines the composition of the system. In order to move to a new epoch, the systems needs agreement by the majority of whoever is in the active epoch.
So here's where all of this leads: Derecho is a concrete implementation of this new-age perspective on Jim's question. Indeed, it is the ultimate story in the sense that the system is optimal in many different ways.
To appreciate this, you'll need to read the Derecho papers, but in a nutshell, the system maps consensus onto RDMA hardware in an exceptionally efficient way. But the protocol itself runs consensus on the configuration of each epoch, and then uses a cheaper consensus protocol within an epoch (one that can assume membership is stable and that failures won't occur), leaving a very clean realization of distributed computing.
Indeed, Derecho is a constructive lower bound in every interesting dimension. It is an optimal solution to the problem of distributed computing, using consensus-based methods.
Why do I make this claim? Well, first, during a given epoch, the system is as quick to deliver messages as is possible: one can prove that any system that delivers messages with fewer "exchanges of information" between its processes is either incorrect, or at last at risk of needing to stop because of some single fault.
Next, one can show that Derecho's agreement on the state of each membership epoch is optimal. Here, Derecho makes use of an all-to-all pattern of information exchange, and I asked Idit if she thought the protocol could be improved. Idit pointed again to her 2006 papers with Alex. Without prior knowledge of which processes failed, and how many failed, she explained, this pattern of information exchange is the quickest way to reach agreement on the membership of the next epoch.
Finally, we can show that Derecho makes progress with a failure model called <>P: eventually perfect failure detection. Idit explained to me that in the past, people actually thought it might make sense to focus on progress with weaker detection models, like <>W, but that if you do so, you either end up with a fault model equivalent to <>P, or you end up with slower agreement protocols that look much more like Byzantine agreement. So, for the style of quick progress Derecho is after, she explains, <>P is the right goal. And Derecho is live with <>P, provided that no more than a minority of processes fail in any epoch. Which again, is the best one can do.
Now, Idit is a theory person, but it is interesting for me as a practitioner to also think about practicalities. As the old adage goes: "In theory, theory and practice are the same, but in practice, they differ."
As it happens, Derecho is optimal in a communications-engineering (networking) sense.
Given that reliable networks always have a one-to-one acknowledgement based layer, reliable multicast over a tree is an optimal data dissemination pattern: if you try and disseminate multicasts over an unreliable 1-N protocol, the cost of detecting lost packets and resending them will be very high compared to a tree of unicast transfers. (Perhaps optical networks with optically aggregated acknowledgements could offer a slight hardware speedup, but even this isn't clear, since the optical aggregator would itself be a tree).
Now if you happen to be a cloud computing engineer, and read the above, what will jump to mind is heavy-tailed behaviors and multi-tenancy: Derecho protocols sometimes relay data, so if a relayer is very slow, everyone waits. Paxos classically would avoid this using quorums: the system doesn't wait for the slowest process. So how can I claim that Derecho is optimal in a practical sense if it doesn't use quorums?
There are a few answers. A long-winded one would talk about work Fernando Pedone and his student, Parissa Jallali, did while visiting my group a few years ago. Basically, they studied quorum behaviors in Paxos and discovered that while Paxos can briefly "outrun" a slow process, eventually work piles up and either flow-control causes the protocol to pause, or a shifting pattern of just who is the slow process switches the slow guy into the quorum and some previous quorum member becomes slow. Either way, Paxos basically halts until everyone catches up and is back in sync. So quorum patterns do not evade the disruption caused by heavy tailed behaviors.
Conversely, offloading the protocol into hardware actually can eliminate that issue, because the hardware is dedicated: the network spends 100% of its time communicating, so if you can describe a pattern of communication, then let it rip, the network is the ideal engine for moving data. As it happens, Derecho generates deterministic data transfer schedules, hence given adequately programmable NICs we can hand the entire sequence of block transfers to the NIC. So we can even make "optimal" use of the network, and since a NIC never sleeps or pauses, quorum behaviors aren't needed even if end-applications sometimes are a bit slow.
So a road that for me started around when Jim asked his question about 2PC seems to have reached its end: Derecho implements the ultimate Paxos protocols for atomic multicast (often called vertical Paxos) and for persisted memory (classic Paxos). We could add an optimistic early delivery protocol with a flush, too, as in Isis and Vsync, but we decided to keep the system simple and omitted it: most people who would use that feature probably just want raw RDMC from the Derecho API, and this we do offer.
And so the Paxos problem is solved. And you know what? Its about time! Idit feels that it was solved back in 2006, actually. As for me, well, until I can write an application using the ultimate protocol, the problem is open. But today, I finally can. (I don't mind at all that Derecho employs a protocol that is actually extremely similar to our first Isis protocols from 1985.)
So should we all pack our bags and go home?
Not quite yet. First, there are other forms of distributed consistency, like convergent (gossip) protocols, self-stabilization, and of course, Byzantine Agreement. It would be nice to see how those fit into this picture and whether there can be a single integrated story that combines all the elements.
A second issue is the engineering complexity of modern platforms. I'll write a whole blog posting on this sometime soon, but suffice it to say that in a data center with physical topology (racks, switches, TOR switches, failure-independence domains...), GPU clusters, NetFPGA accelerators, Intel SGX protection enclaves... it just isn't obvious how to write code for such environments. Derecho is just part of the answer, and not the whole story.
Then beyond all of this are dimensions we have yet to tackle in Derecho itself. For example, even if Derecho is the ultimate data center protocol, is it also the ultimate WAN version? As it happens, I suspect that this may be true too, but more attention to the question will be needed. Anyhow, until we have it running, I won't believe the story even if I figure it out "in theory". After all, in theory, theory and practice are the same... but in practice, they are enormously different.
So I wouldn't despair: very likely we are finally at the end of the road for Paxos, but it certainly isn't the end of the road for distributed systems. Watch this space: I can promise plenty of interesting new questions, and new answers, in years to come.
Wednesday, 28 December 2016
Next generation memory technologies
During the past few months I've had time to talk to Dave Patterson (Berkeley), Dave Cohen (Intel) and Pankaj Mehra (Sandisk/WD) about the next generation memory hierarchy. This blog seems like a good way to organize what I'm learning and to jot down a few thoughts.
First, we're about to see another major technology dislocation, similar to that associated with RDMA (and actually it will include an RDMA dimension). Here's why I say this:
First, we're about to see another major technology dislocation, similar to that associated with RDMA (and actually it will include an RDMA dimension). Here's why I say this:
- There are a LOT of a new technologies in the pipeline, including 3-D XPoint memory, much larger SSD (NAND) storage systems with battery-backed DRAM caches, phase-change memory, and probably more. For those unfamiliar with the terms, normal computer memories are usually referred to as SRAM (the super fast kind used for registers) and DRAM (main memory storage).
- They have very different properties. 3-D XPoint is a persistent memory technology that can run nearly as fast as DRAM when evaluated purely in terms of throughput, and with only a very small access delay (a few clock cycles more than for DRAM). It offers full addressability and byte-by-byte atomicity, and it can keep up with RDMA, so we should be able to direct RDMA data streams directly into 3-D XPoint persistent storage. The issue for 3-D XPoint is likely to be its initial price: until volume becomes very large, this will be a fairly costly form of storage, more similar in price to DRAM memory than to SSD/NAND flash.
- Battery backed flash (SSD/NAND) has been around for a while. It takes an SSD disk and then puts a large DRAM cache in front of the disk, with a control processor and a battery to keep the unit alive even if the host machine crashes. The idea is that once you've written to the DRAM cache (which you can do at full speeds and even using RDMA), you won't have to worry about persistency because if power is lost or the host crashes, the little control device will finish any pending transfers. But because NAND has lower transfer rates, you run into the issue that at RDMA speeds you can easily fill the entire cache before the system would have time to DMA the data onto the back-end flash storage system, so any high speed solution will need to either limit total transfer rates or stripe data across a bank of these units.
- Rotational disk is quite slow by the standards of either of these technologies, but with new coding techniques ("shingling") offers some benefits that neither of the others possesses: it has really massive capacity, and doesn't suffer from "write leveling", a notorious problem for flash (if you rewrite a block too many times, the block degrades and can no longer record the data).
I didn't list phase-change memory here because I don't know as much about it, but people tell me that it has huge potential as well. I mentioned that 3-D XPoint will initially be fairly expensive (unless companies like Intel decide to price it low to push volumes up quickly). In contrast, SSD and rotational disk remain quite cheap, with SSD relatively more expensive than rotational disk, but quite a bit cheaper than 3-D XPoint. On the other hand, if you put a battery-backed cache and an ARM co-processor on your SSD store, it becomes a much more costly storage solution than it would be if you had one battery-backed DRAM cache for the whole system and shared it across your fleet of SSD disks.
We need to think of these memory technologies in the context of other technologies, such as:
- RDMA, mentioned above.
- NUMA hardware: with modern multicore systems, a memory unit can be close to a core or further away. It is very important to ensure that your memory blocks are allocated from nearby memory; otherwise every access can incur a huge penalty.
- NetFPGA coprocessors, and GPU coprocessors: increasingly popular and able to run at line data rates but only if the pipeline is very carefully crafted.
- Other forms of data capture and data visualization hardware that might use DRAM as their main way to talk to the host (your display already does this, but we'll see more and more use of 3-D visualization technologies, novel forms of video recording devices and new interactive technologies).
- Various forms of caches and pipelines: each technology tends to have its own tricks for keeping its compute engine busy, and those tricks invariably center on pipelining, prefetching, data prediction, etc. If we move data around, we potentially move data from or into memory being computed upon by some device, and then either we might see the "wrong" data (e.g. if a specialized compute engine signals that it has finished, but its results are still in a pipeline being written to the output memory), or we might start the specialized compute engine up prematurely. In fact we even see this with our battery-backed DRAM/NAND mix, or with 3-D XPoint, where is takes a few clock cycles before data written to the device has really become persistent within it.
Some of these technologies are block oriented: the main processor cache operates in terms of blocks that we call "cache lines", an SSD would normally be structured into blocks of data, and a rotating disk invariably is. Others are byte addressable, like 3-D Xpoint and DRAM.
So we have quite a range here of speeds, price points, and addressability models. More complications; to the extent that these technologies have pipelines or caches or other internal memory structures, there isn't any standard way to flush them. Thus when I receive an RDMA data transfer into my machine and the RDMA NIC interrupts to say "data received", it isn't always obvious when it would be safe to use that data, and how. RDMA vendors ensure that CPU access to the received data will operate correctly: I can do any kind of computation on it that I want, or initiate a new outbound RDMA. But I want to turn around and ask my GPU to compute on the received data, it isn't obvious how to ensure that the GPU subsystem won't have cached some form of data of its own, that the RDMA transfer overwrote and hence invalidated, and if I can't flush those caches, I have no good way to be sure the GPU will "see" my new bytes and not the old ones!
A further puzzle is that in a rack-scale setting with NUMA machines, memory management potentially becomes very complex. RDMA makes it pretty much as cheap to pull in data from other machines as from my own: after all, the RDMA network runs as fast or faster than the DMA transfer from an SSD or a rotational disk. So the entire cluster potentially shares a huge amount of persisted memory, subject to just small latencies for accessing the first byte, provided that my transfers are large. With byte addressing, local DRAM is vastly faster than remote 3-D XPoint accessed over RDMA: even if the access will be handled by hardware, we can't eliminate those microseconds of setup delay.
Here's another thought: suppose that we shift perspective and ask ourselves what the application itself is likely to be doing with all of this persisted storage. I like to use two examples to shape my thinking. The first is that of self-driving cars sharing a huge world model that they read and update (the world model would include descriptions of the cars and their "plans" but also of everything they encounter and might need to chat about: other vehicles that aren't using the same self-driving technologies, pedestrians, transient road conditions like black ice or potholes, etc). And my second example is that of a bank logging financial transactions.
Here one instantly notices that there would be a need to keep fresh data easily accessible at low delays, but that older data could either be garbage collected or archived. So beyond the need to manage memory even for immediate uses, there is a broader need to think about "long term data curation". In the case of the bank, protection becomes an issue too: both to protect secrets and also to prevent tampering.
I don't have a magic answer here (nobody does) but I do think the picture highlights a huge opportunity for research in the operating systems and storage communities. Honestly, this looks to me like a situation in which we need a whole need operating system specialized just on these questions: there is an issue of what the proper abstractions should be, and how one would program against them, and how the technologies enable doing so (or prevent us from doing so).
Then we should ask about new opportunities. The self-driving car example points to a deep integration of storage with machine-learning applications. What are the access patterns that arise in such cases, and how does this shape our caching needs? What about replication? We clearly will need to replicate data, both for fault-tolerance and for speedy local access in the case of byte-addressing data where low-latency is key. Get such questions right, and suddenly we open the door to new kinds of medical devices that capture, process and display imaging as the operation advances; get them wrong and the same mix of hardware might be useless in the operating room!
I'll stop here: my blog entries are always way too long. But what an exciting time to do research in systems... I'm jealous of the young researchers who will get a chance to really tackle these open questions. And I'm looking forward to reading your SOSP papers once you answer them!
Wednesday, 7 December 2016
Transactions [4]: How does a system like Derecho fit in a world with transactional DHTs?
Derecho is Cornell’s new RDMA-based data
replication solution. It is a simple
library coded in C++ 14 (well, maybe not that
simple, but simple to use) and it automatically interfaces your code to the
local RDMA hardware. It also automates
such tasks as initializing new members when an application process joins an
active application or restarts after a serious crash (state transfer),
membership coordination and update when members join or fail, persistent data
management, atomic multicast, and even RPC (but we also allow you to interface
to a Derecho application with standard RPC packages like RESTful RPC or WCF).
What I find interesting is that (1) Derecho can be understood in terms of transactional consistency for atomic "one-shot" operations. (2) In fact these consistency guarantees extend to aspects of distributed application structure that are not normally considered to need consistency, (3) The really interesting use cases might actually need both Derecho and something like FaRM.
Derecho Primer (mostly duplicates content from the RDMA Derecho posting)
So let's get there step by first. I'll start with a bit of a duplicate, since I discussed Derecho on the RDMA thread too. But just in case you skipped that, this illustrates an application of
the kind Derecho can help you create:
In this example, the really small white
circles are processes: instances of a program, each running on some
computer. The picture thus could span
tens or even thousands of nodes in a cluster or datacenter. We’re trying to help you structure large
numbers of processes into cooperating applications where each process plays a
specific role within the larger picture.
This particular application has external
clients that use browser technologies to talk to it: the red squiggles on the
top left. For example they might use
RESTful RPC, which encodes RPC requests as web pages (and similarly for the
replies). REST is widely support but not
very fast, which is why we also have a point-to-point RPC layer internal to
Derecho. Most applications using Derecho
would use our layer internally even
if they talk to the external world
using REST or something similar.
The next Derecho concept is that of the top level group. This is the full membership of the whole
application. In the picture we can see
that the top-level group has (at least) 13 members, because there are 13 explicitly
shown tiny little white circles. For
most uses the members are actually running identical code, but playing distinct
roles. How can that be? Well, membership is a kind of input, and each
program in a Derecho application knows its respective membership rank (1 of 13,
2 of 13, etc). So this is enough for
them to specialize their behavior.
There is a standard way to specialize
behavior, and the picture shows that as well: we associate C++ classes with the
top-level group. This example has 3
classes: LoadBalancer, CacheLayer, and BackEnd.
Each is a normal C++ class, but registered with Derecho. There is also a notification class, used by
the back end to talk to the cache layer (purple circles).
Derecho uses little functions to define
subgroup membership. They actually are
implemented using C++ lambdas. One such
lambda told Derecho that the first three members of the top-level group would
be the load-balancer, and we see that at the top. Another indicated that the cache layer is
sharded; in this configuration it seems to have at least 3 shards. Further, the shards have 3 members each, and
there is a shard generator (built into Derecho) that assigned 9 members to this
role. Last, we see that the back end
store is also sharded, with 2 replicas per shard, and 4 members in total.
Derecho has all sorts of options for
sharding (or at least it will when we finish work on v2 of the system). Shards can overlap, there can be members
held in reserve as warm standby processes to jump in instantly after a crash,
etc. Subgroups and shards can overlap…
whatever makes sense to you as the designer.
Next, Derecho has ways to talk to these
groups, subgroups or shards: via atomic multicast, which can also be logged
into persistent storage. The latter case
matches the specification for Paxos, so in effect, Derecho is a scalable Paxos
with an in-memory or a disk execution model, and you can select between the two
cases when designing the various components of your application. The system automatically cleans up after
crashes and makes sure that messages are seen in the same order by all members
and so forth.
So with about 15 lines of C++ code per
class, more or less, you can instruct Derecho to set up a structure like the
one seen here. And then it just takes a
line or so more to send an RPC to some specific member, or issue a multicast to
a subgroup or shard, or even to query the members of a subgroup or shard. The actual delivery of new membership reports
(we call them views), multicasts and
RPCs is via upcall to methods your class defines; the style of coding looks
like a kind of procedure call with polymorophic arguments, and in the case of
queries (a multicast to a group where each invoked function returns a result
object), you can iterate over the replies in a for loop.
Derecho is blazingly fast. The API is quite simple and clean, so there
isn’t a lot of infrastructure between your code and the RDMA network, and we’ve
done some really interesting work to maximize performance of our RDMA sends and
multicast operations. Learn more from
the Derecho papers on http://www.cs.cornell.edu/ken,
and download the open-source distribution from GitHub.
Derecho plus FaRM
Visiting at MSRC got me thinking about cases where you might want both Derecho and a transactional DHT, like FaRM or HERD. I came up with this:
What you see here is two applications, both using Derecho (task A and task B), and then a transactional DHT sitting between them (more properly, present on the same cloud, since all of these span lots of compute nodes).The case I'm thinking about might arise in a setting like self-driving cars. Suppose that task A is a helper application for self-driving cars on California highway 101. It scales out (hence needs lots of read-oriented replicas in the caching layer), has state (car positions and plans), and needs consistency. And suppose that task B is handling California 280, which is also quite a busy throughway (so it needs its own smart highway helper), but has some overlap with 101. In fact California might need ten thousand of these tasks just to cover all its busy highway segments.
So we have complex scaled-out applications here, that need replication for high availability, fault-tolerance, and very strong consistency, built using Derecho. The internal state of each lives within it, including persistency. But when these tasks share state between tasks -- with external "users", the need is different. In our illustration, we use a transactional DHT to store state shared between these complex, structured applications.
My thinking here is that the DHT is a very good fit for a kind of anonymous sharing: task A wants to report on vehicles that are likely to leave highway 101 for highway 280, but on the other hand doesn't want to "talk directly" to task B about this, perhaps because the sharing model is simply very convenient this way, or perhaps to avoid interdependencies (we don't want task A jamming up if task B is very busy and slow to respond to direct queries). Anyhow, the manager for route 1, along the coast, might periodically do a quick scan to plan ahead for cars that might be leaving 101 to join route 1 in the future, etc. By using the DHT we can support a kind of unplanned sharing.
In contrast the Derecho form of consistency is a great fit for the availability and fault-tolerance needs of our individual tasks -- busy, scaled-out, complex systems, that need consistency. The DHT wouldn't easily support that sort of application: a DHT like FaRM lacks any notion of a complex, long-lived application with state replicated across its member processes. FaRM uses replication, but only for its own availability, not to replication application roles or functionality.
So my belief is that we are heading towards a very large-scale world of demanding IoT applications that will really need both models: replication in the form a system like Derecho offers for application design and structure, and transactional DHTs for anonymous sharing. But I guess we'll have to wait and see whether the application designers faced with building smart highways agree!
Subscribe to:
Posts (Atom)



