As the resolution with which scientific tools can measure experiments increases, so, too, does the amount of data they produce. Diverse fields such as particle physics (CERN, 2012), bioinformatics genome sequencing (Mardis, 2011; Nothaft et al., 2015), medical imaging (Sarraf and Ostadhashem, 2016; Boubela et al., 2015), aeronautics (Bernard Marr, ), and IoT produce data with a growth rate that exceeds Moore’s law. Users typically process such data sets with cloud computing frameworks that separate application logic from execution, delegating the latter to a common runtime deployed across large clusters of machines (Chintapalli et al., 2016; Veiga et al., 2016). These frameworks expose abstractions such as basic map-reduce (Dean and Ghemawat, 2008), but more general-purpose frameworks (Isard et al., 2007; Chambers et al., 2010; Zaharia et al., 2012; Murray et al., 2013) encapsulate application logic in a directed acyclic graph (DAG), with each node expressing an operation (e.g., reading a file) and the edges expressing data dependencies between nodes. Each framework’s runtime is responsible for (a) instantiating the operations and stateful elements contained in the DAG across a set of scale-out hardware resources and (b) managing the execution of the application according to the logic corresponding to the DAG.
The specific type of framework typically used in big data scientific processing are batch frameworks. Each request to the framework (e.g., from a client program or work queue) corresponds to a finite number of data items, e.g., the locations of all files to read and process. Applications written with batch frameworks are instantiated once and process an unending stream of requests.
Cloud computing frameworks employ the pipelining concurrency strategy to more effectively utilize a cluster’s hardware resources. Frameworks typically pipeline the data items in a request across the nodes in the application’s DAG; based on the semantics of the framework and the logic in the application DAG, each node in the DAG may concurrently process different data items from a request. This increases the overlapping of computation with I/O, which increases hardware resource utilization. Frameworks may pipeline requests as well, thereby overlapping the concurrent processing of data items from multiple requests.
TensorFlow is a popular framework built on the dataflow abstraction that targets machine-learning applications. TensorFlow encodes application logic using a DAG and includes a large library of nodes for mathematical operations; it is a popular choice in the machine learning domain, with applications to cancer research, medical imaging, retinal disease, and physics (Esteva et al., 2017; Salimans et al., 2016; Litjens et al., 2017; De Fauw et al., 2018; Vilsmeier et al., 2018)
. TensorFlow’s highly optimized runtime instantiates application graphs across multiple machines, places each node on a machine, and inserts the necessary communication mechanisms between nodes on different machines or to a hardware accelerator. The runtime is written in C++ to take advantage of heterogeneous hardware, including CPU vector units, GPUs, and even custom ASICs(Jouppi et al., 2017).
The performance of TensorFlow’s native execution provides an ideal basis for a cloud computing framework for scientific applications as well as machine learning applications. Contemporary JVM-based cloud computing frameworks can impose a 16-43 overhead for analytics workloads as compared to a framework based on C++ (Mashayekhi et al., 2016). The JVM (Lindholm and Yellin, 1997) itself imposes overheads for of 1.9-3.7 compared to a native language for computationally-intensive applications (Hundt, 2011; Gherardi et al., 2012). Scientific applications are heavily impacted by such overheads due to their high ratio of cycles per byte of I/O (Bell et al., 2006; Schadt et al., 2010).
Unfortunately, a key design decision limits TensorFlow’s applicability as a general-purpose cloud computing framework: TensorFlow cannot pipeline multiple requests within the runtime. Although TensorFlow can pipeline data items of a single request, it cannot distinguish data items associated with different user requests. While workarounds exist (e.g., performing the disambiguation in the client code controlling TensorFlow via the Python API), this leads to expensive data conversion (Palkar et al., 2017). This limitation is acceptable in TensorFlow’s target domain of machine learning, which typically runs applications with a single coarse-grain graph representing a long-running computation.
This paper presents Pipelined TensorFlow (PTF), a system that bridges this gap between TensorFlow and cloud computing frameworks. PTF enables the continuous execution of concurrent, multi-request pipelines — a key functionality for cloud computing frameworks — within the TensorFlow runtime. PTF applications can overlap the parallel operation of application I/O and compute phases. PTF adds two key properties to TensorFlow:
Concurrent and isolated execution: PTF provides the abstraction of an isolated pipeline for each request. Regardless of when the request is submitted to an application or the number of concurrent requests, PTF ensures that each request is processed as if it were the only request submitted to the application.
Bounded resource utilization: PTF implements a two-level, credit-based flow control within an application’s pipeline to ensure bounded resource utilization when concurrently processing a stream of requests. This is crucial for memory-intensive, scientific applications, which should operate without swapping, for efficiency. The two-level scheme separates flow-control considerations within and across machines.
PTF adds three abstractions to TensorFlow that enable multi-request pipelining. (1) Stages encapsulate TensorFlow graphs representing a small subcomponent of the application’s logic. (2) Gates separate adjacent stages and use additional metadata to differentiate inputs between concurrent requests. (3) Pipelines are composed of a series of gates and stages. PTF implements these abstractions entirely within the existing TensorFlow runtime as a small additional library of code in the TensorFlow codebase.
Our contributions include:
Three new abstractions (stages, gates, and pipelines) that extend TensorFlow’s semantics and capabilities to enable multi-request pipelining
PTF, a backward-compatible patch to TensorFlow that implements these new abstractions
PTFbio, a high-throughput, pipelined bioinformatics application service. PTFbio integrates the Persona (Byma et al., 2017) data format and aligners into PTF.
We evaluate PTFbio to characterize PTF’s scale-out behavior on a cluster of 20 servers. We show that (a) the use of pipelining increases throughput by 4 while only increasing the average latency of processing an individual request by 0.13 and (b) linear speedup to the size of our cluster.
PTF is open-source and can be found in the following repositories:
https://github.com/epfl-dcsl/ptf-system, which contains the code for PTF and Persona as additions to a standard TensorFlow code repository.
https://github.com/epfl-dcsl/ptf-persona, which contains the Python code that constructs and executes local and scale-out applications using PTF.
We refer the reader to the documentation in these repositories for further details.
The rest of the paper is organized as follows: §2 provides the necessary background on cloud computing frameworks and TensorFlow. We then discuss the architecture (§3) and implementation (§4) of PTF. In §5, we describe the construction of PTFbio, including a novel fused alignment/sort step in the pipeline. We evaluate the performance of PTF (§6), discuss related work (§8) and conclude (§9).
This section describes the paradigm of contemporary cloud computing and streaming frameworks, TensorFlow’s dataflow model, and how they differ.
2.1. Cloud Computing Frameworks
Cloud computing frameworks (Akidau et al., 2015; Carbone et al., 2015; Zaharia et al., 2013; Isard et al., 2007; Kulkarni et al., 2015; Apache Samza, ; Amazon Web Services, ; Murray et al., 2013; Lin et al., 2016; Zaharia et al., 2012; Dean and Ghemawat, 2008; Chambers et al., 2010; Toshniwal et al., 2014; Akidau et al., 2013; Mashayekhi et al., 2017)
are a popular architecture to orchestrate data processing in data centers because they separate application logic from execution. Application logic is typically encoded as a directed graph of data dependencies between successive nodes, each of which performs a modular subcomponent of the application’s overall logic (e.g., reading a file, summing all input values). This graph is typically acyclic, or contains a few coarse-grained loops, e.g., a global loop to train a classifier. The framework’s runtime executes the application by launching a set of tasks (e.g., threads, processes, containers) on the underlying hardware that each execute one or more kernels corresponding to nodes in the graph. The runtime enables application developers to focus on the application logic, not on the low-level details of how the logic is implemented; the graph is not a procedural specification of the computation.
Cloud computing frameworks increase resource utilization by concurrently processing requests. An application written using a cloud computing framework is typically allocated a fixed set of resources upon instantiation by a resource manager (Vavilapalli et al., 2013; Brewer, 2015; Hindman et al., 2011; Verma et al., 2015); each request submitted to the framework uses a subset of these resources. As the framework processes a request, it must (a) adapt the subset of resources allocated to each request based on all request-associated allocations (e.g., delaying requests to avoid over-allocation) and (b) provide the semantics of an isolated set of resources to each request so that the result of a request is not affected by concurrently-executing requests.
Delegating resource partitioning to a cloud computing framework enables fine-grained resource partitioning schemes that maximize resource utilization. Permanently assigning hardware resources to a request wastes resources because the resource manager has little insight into the application logic. The associated overhead is due to: (a) resource stranding within an application (e.g., allocation of an expensive resource that cannot be shared between requests), (b) the necessity to run multiple copies of the same application logic (one per request), and (c) the constant allocation and deallocation of shared resources. By using application logic to determine when and how to safely share and partition resources, cloud computing frameworks can multiplex concurrent request processing at a finer granularity.
Data pipelining is a common strategy used to achieve this finer-granularity resource sharing. Pipelining is the concurrent processing of distinct data items by different operations in the application logic, i.e., corresponding to different nodes in the DAG. These data items may be associated with the same request or different requests, depending on the capabilities of and semantics supported by the framework. By overlapping different computations in the application, the cloud computing framework’s runtime may use a greater portion of the underlying hardware resources at any given time, e.g., overlapping a node performing I/O with another doing computation. This pipelining strategy also increases the likelihood that any given node in the application’s DAG will have an input ready when it finishes processing a data item, thereby spending less time waiting for input from upstream nodes in the application DAG.
2.2. TensorFlow Programming Model
TensorFlow uses dataflow to express application logic as operations on tensors. Dataflow represents application logic as a DAG: nodes represent operations and edges specify the propagation of the results. TensorFlow’s features and design decisions are based in its focus on the machine learning domain; most of its predefined nodes perform stateless numeric computations. Each node consumes and emits only tensors, multi-dimensional arrays of a single elementary data type (numerical or string).
TensorFlow graphs process tensors using a push model of execution. A feed is a group of tensor values that populate placeholder inputs to a graph. The client program inputs a feed into a graph and requests the value of the graph’s output, i.e., a downstream group of tensors. The TensorFlow runtime responds to this request by propagating the feed through the graph based on a strict set of rules (Abadi et al., 2017; Arvind and Nikhil, 1990). The result is a new feed (corresponding to the downstream tensors) and side effects, e.g., updating a stateful variable held by a graph node.
A batch of feeds is a collection of related feeds that together form the input for an application, e.g., a series of labeled images on which to train a machine learning model (Deng, 2012). Upon startup, TensorFlow applications initialize stateful variables (e.g., large tensors that hold persistent data across successive feeds) and then process a batch of feeds. The client program drives each feed through the TensorFlow runtime in succession, updating the variables each time. A single graph may process concurrent feeds from a single request, but extra information must often be added to the graph in order to serialize parallel updates to variables.
Monolithic application graphs can be decomposed into smaller graphs separated by TensorFlow queues. Each TensorFlow queue separates successive phases of an application into distinct independent graphs; these graphs are linked by the TensorFlow queue data structure that buffers feeds between upstream and downstream graphs. This separation increases concurrency within an application. For example, an initial phase typically reads in a batch of feeds from storage (training examples) and a subsequent phase trains a model based on the values. Each graph receives a feed from its upstream queue via a dequeue node and sends the resulting feed to its downstream queue via an enqueue node. Each graph is driven by a queue runner, i.e., a Python thread containing no application logic that drives feeds through a graph by requesting the value of the graph’s enqueue node.
The TensorFlow framework targets applications that process a single batch of feeds per invocation. While internal concurrency between feeds is possible, TensorFlow does not natively distinguish between feeds belonging to different batches of inputs. A multi-batch TensorFlow application must rely on the client program to disambiguate between feeds from different batches. The necessary performance penalty for involving the client program is the copying of data into and out from the TensorFlow runtime. Machine-learning TensorFlow applications are not inhibited by this design decision, as they typically do not concurrently process multiple batches; their graphs contain computationally-intensive coarse-grained operations that have little overhead to construct on a per-batch basis.
PTF is a cloud computing framework built on TensorFlow that allows for concurrent, isolated, and flow-controlled processing of a stream of successive requests. These requests correspond to batches of feeds and are supplied from a common single queue. PTF dequeues requests from the queue in succession and processes them to completion entirely within the TensorFlow runtime.
PTF is a careful addition of code to TensorFlow to enable pipelines of TensorFlow graphs to process concurrent batches within the same invocation of an application. This pipeline of independent TensorFlow graphs enable PTF to support data pipelining: all graphs in the pipeline can simultaneously process different data items (feeds). This architecture enables semantics necessary for PTF to operate as a more general-purpose cloud computing framework, performing both data processing and batch management (i.e., tracking the progress of each batch in a pipeline); it does not rely on an external framework or client-side code (i.e., code calling into the TensorFlow runtime via its API) in order to perform any of its operations, thereby avoiding expensive data copying.
The key insight of PTF is the association of an additional metadata tensor with a feed. The metadata tensor embeds the necessary information to (a) identify the batch to which a feed is associated and (b) describe the batch. PTF interprets the metadata directly in the TensorFlow runtime. Passing this metadata as a tensor within a feed enables PTF to reuse TensorFlow’s runtime to pass management information with data.
PTF inherits key attributes from TensorFlow: (1) it allows for the concurrent execution of an arbitrary graph across multiple cores and heterogeneous hardware components; (2) it scales out across multiple machines with negligible overheads by forgoing the need for any global coordination when partitioning the workload across machines.
PTF expresses applications as a pipeline of successive stages synchronized via connecting gates. Each stage is a TensorFlow graph that statelessly transforms feeds to apply the subcomponent of the application logic it represents. The gates synchronize and coordinate the concurrent execution of different feeds throughout the pipeline. This decomposition of a large TensorFlow graph into smaller graphs (stages) decouples the large chain of data dependencies between input and output, enabling PTF’s gates to interpose between different stages to apply its new functionality.
Figure 1 shows the details of a stage. The TensorFlow graph in the stage interacts with adjoining gates via enqueue and dequeue nodes to send and receive feeds, respectively. A stage runner thread drives the stage’s graph with successive invocations via the Python API, repeatedly checking the upstream gate to trigger the TensorFlow runtime to execute the stage on new feeds; stage runners serve a similar purpose as queue runners for TensorFlow queues, i.e., driving the execution of a stage without performing any logic in the Python code. The metadata tensor from the feed is passed around the core TensorFlow graph, as the application logic of the graph does not alter the metadata tensor.
Gates store feeds in a buffer between successive stages so that a pipeline may execute multiple feeds concurrently. Similar to TensorFlow queues, gates interpose between adjacent separate graphs to decouple the direct data dependencies between two successive stages. Gates use this decoupling to apply their custom concurrency and pipelining logic, as they are able to regroup, reorder, or delay the feeds without usurping TensorFlow’s dataflow rules.
Gates coordinate data availability and buffering between adjacent stages. Once a stage processes all tensors in a feed, it atomically inserts the entire feed into its downstream gate. The gate buffers the feed until the downstream stage requests a new output from the gate. The gate then selects a feed from its buffer and atomically transmits all feed elements to the downstream stage for processing. The execution of each stage is limited by the availability of a) a feed from the upstream gate and b) capacity to enqueue the resulting feed into the downstream gate. Any stage that has both may execute concurrently with any other stage in the pipeline.
Gates interpret the metadata contained in a feed to apply PTF’s concurrency and pipelining semantics. When a feed is enqueued into a gate, it is stored and dequeued based on its associated batch. As concurrent batches progress through a pipeline, each gate stores and forwards the constituent feeds such that the result of processing any given batch is identical to processing the batch in a non-multiplexed pipeline. This isolated pipeline abstraction is enabled by the custom logic in the gates and the stateless nature of stages. The custom logic is performed directly in the TensorFlow runtime so that PTF does not rely upon an external framework or client program.
The metadata consists of two integers: an ID and an arity. The ID is a unique numerical identifier assigned to a batch when it enters a PTF pipeline. The arity is the number of feeds in the batch. By construction, all feeds from the same batch will have identical metadata.
3.2. Gate Operation
Gate operations update the state of the gate by inserting or retrieving a feed with its associated metadata. A stage’s graph first dequeues a feed from the upstream gate via a dequeue node. Once that feed has propagated through the stage’s graph, it terminates in an enqueue node, which inserts the feed into downstream gate. Both the enqueue and dequeue operations are synchronous: further computation in the stage blocks until their respective operations complete.
Gates serve enqueue and dequeue operations from a single operation queue, protecting concurrent access to its internal data structures with locks. A gate may reorder operations in the queue based on its operational semantics. For example, an enqueue operation will be served before any dequeue operation if there are no buffered feeds. In the common case, these operations are performed in a first-come, first-serve (FCFS) order.
Gates interpret the metadata to track and control the progress of batches through the application pipeline. The gate examines the ID of a feed to determine if the feed is from an existing batch. If the feed is associated with a new batch, the gate allocates space in its feed buffer for the batch and inserts the new feed. If the feed belongs to an existing batch, the gate inserts the feed into the preallocated feed buffer space for that batch.
Gates control the lifecycle of a batch by deciding when to open and close each batch it processes. A gate opens a new batch by beginning to send feeds from the buffer. Dequeue operations remove feeds from the buffer until the gate determines that no more feeds will be available by examining the metadata arity and the number of feeds buffered and dequeued. The gate closes the batch by freeing the associated data structures, including the space in its feed buffer. A batch may be opened before all of its feeds have been enqueued into the gate.
Gates may emit feeds in any order from any open request. When selecting which feed to emit to the downstream stage through a dequeue operation, a gate may choose any feed from any request that is open and has feeds buffered. This loose ordering guarantee enables PTF to improve concurrency and feed pipelining by increasing the number of feeds buffered in the gate that are candidates to emit downstream. In practice, gates emit feeds in preferential order in which batches are opened; feeds are emitted in FIFO order within a given batch, based on their arrival into the gate via an enqueue operation.
Gates use special variants of enqueue and dequeue operations to consume and produce aggregate feeds. Gates combine multiple individual feeds from a batch to produce an aggregate feed, which contains the same number and type of tensors as the original feed type, but with an additional dimension added to each tensor in order to group the individual feeds’ tensors (e.g., a vector to a matrix). Aggregate dequeue operations change the arity because the reduce the total number of feeds in the batch; the downstream stage consuming an aggregate feed must produce a single output feed, thereby reducing the arity by the aggregation size. If the requested aggregate size is and the original arity is , then the new arity is calculated as . All of the feeds in each aggregate feed produced by the aggregate dequeue operation originate from the same batch and contain individual feeds, except for the last aggregate feed produced for the batch that may contain feeds if that value is greater than 0.
Aggregate dequeue operations are used for a variety of purpose in a PTF pipeline. They can be used to provide multiple input feeds at once to a stage, which may enable more efficient nodes to be used in the stage’s graph. An aggregate dequeue operation can serve as a barrier in a PTF pipeline by aggregating all items in a batch before emitting them downstream; in this case, the requested aggregate size must be greater than any batch’s arity.
3.3. Resource Bounding
PTF provides credit-based flow control between any two gates. Each credit in PTF represents the ability of a gate to open a new batch. Credits are issued by a downstream gate to the linked upstream gate. When the upstream gate receives a credit, it may open a new batch and begin to send the associated feeds. When a gate closes a batch, it increments the number of available credits, sending them to the upstream gate if one is linked.
Gates can locally limit the size of their feed buffer to control resource usage regardless of batch size. A gate with a non-aggregate dequeue may limit the total size of its feed buffer for all open batches. When the feed buffer is full, enqueue operations block until subsequent dequeue operations free space. This resource bounding mechanism is similar to that which is used by TensorFlow queues to bound resource usage.
3.4. Stage Parallelism
A PTF application can replicate any stage to scale out across local hardware resources. Replicating a stage exposes more nodes to the TensorFlow runtime, which increases the degree of parallelism subject to feed availability from the upstream gate. A stage is replicated by copying its TensorFlow graph, stage runner, and inserting new enqueue and dequeue nodes for each replica. Each replicated stage operates independently of other stage replicas; it executes only when the upstream gate sends an input feed to it. The upstream gate serves stage replica requests in FCFS order.
3.5. Pipeline Hierarchy
PTF scales out pipelines across multiple machines by using a two-level nesting hierarchy of local and global pipelines. A local pipeline consists of gates and stages that are placed in a single process (typically one process per machine). A global pipeline consists of a sequence of local pipelines separated by global gates. An application can replicate a local pipeline onto multiple machines to scale out across additional resources. Gates in the global pipeline coordinate progress of batches in the local pipelines. Global gates may be placed on any machine in the cluster; by default, PTF places them on a single dedicated machine to not disrupt local pipelines.
Global pipelines distribute batch partitions to minimize communication overhead when distributing feeds to local pipelines. A partition is a subset of a batch in the global pipeline that is distributed to a local pipeline. A local pipeline processes each partition it receives as a standalone batch. Distributing partitions instead of feeds from a global batch avoids a scaling bottleneck by decoupling coarse-grained partition distribution from fine-grained feed processing.
Gates in the global pipeline create partitions by performing an aggregate dequeue operation and modifying the metadata to contain the ID and arity of both the original batch and the partition. Local pipeline gates use only the partition metadata to perform their operations. The subsequent global gate reassembles the original batch by stripping away the partition metadata and using only the batch metadata.
PTF bounds resources using a hierarchical flow control scheme. Each gate within a local pipeline may bound upstream gates within the same local pipeline with a local credit link. Gates in the global pipeline may bound upstream global gates in order to limit global resource usage with a global credit link. Although credit linking in both the global and local pipelines does not provide a tight bound on the total resource usage (due to the fact that a given batch may contain any number of feeds), it prevents gates upstream of a thoughput-limiting stage (e.g., one that performs a computationally-intensive process) from accepting an unlimited number of feeds in steady-state operation. Gates in either the local or global pipeline may limit the size of their feed buffers.
Figure 2 shows an example of a PTF application that scales across machines using global and local pipelines. This shows the baseline application for PTF Persona with three local pipelines: align, sort, and merge. Pipeline and stage replication are used to scale across global and local resources, respectively. Gates in both the global and local pipelines make use of aggregate dequeue operations: the sort stage in the sort pipeline operates on aggregates of size () and the merge pipeline requests partitions containing the entire batch of size ().
3.6. Computational Model
PTF does not change the standard TensorFlow semantics (Abadi et al., 2017); it partitions monolithic TensorFlow graphs into smaller graphs (i.e., stages) in which the existing semantics apply. By splitting the application into stages, PTF applies standard TensorFlow semantics within each stage and interposes between stages to apply pipelining semantics with gates. This enables PTF to use the TensorFlow runtime with no modifications, including the reuse of the existing features in TensorFlow such as (1) the distributed runtime, (2) the ability to serialize the entire application for distributing to each node and exporting, and (3) the myriad existing TensorFlow nodes.
PTF is backward compatible with TensorFlow, i.e., any TensorFlow node used to construct a TensorFlow graph may be used to construct a PTF graph. Note, however, that a TensorFlow program often consists of a graph combined with client logic, described in §2.2, which typically iterates over feeds until some termination condition is met. PTF, with its design goal for cloud computing applications, does not support client-driven logic not expressed in the graph. Instead, PTF submits each feed exactly once to the graph and any iterative or conditional construction must be expressed within the graph itself.
PTF uses the dataflow semantics of TensorFlow to avoid using a centralized scheduler. When a stage dequeues a feed and its associated metadata, TensorFlow’s guarantees that the stage’s graph emits exactly one resulting feed after processing the input feed. This guarantee ensures that the metadata remains a valid description for all feeds in any given batch because neither the ID nor the arity can be invalidated by unpredictable graph behavior (e.g., emitting more than one result feed for a given input feed). TensorFlow’s exactly-once delivery semantics ensures that each gate only receives a given feed once. Gates rely on this guarantee to track the progress of concurrent batches without a centralized or broadcast-based scheduling architecture; the metadata provides sufficient information for any gate to locally track the progress of a batch based solely on feed arrival, regardless of the complexity of the upstream and downstream stage graphs.
The PTF patch to TensorFlow consists of 2476 lines of C++ code and 841 lines of Python. Apart from the build system, PTF does not require modifications to the TensorFlow runtime or existing library of nodes. The patch defines gates, stages, and pipelines, which are exposed via the Python API to enable a user to construct a PTF application.
The core PTF API defines gates and gate operations. Gates are instantiated as shared resources within the TensorFlow runtime. The enqueue and dequeue operations that manipulate a gate’s internal data structures are colocated in the same process as the gate.
PTF applications utilize TensorFlow’s distributed runtime to coordinate global and local pipeline execution. An application first creates the complete TensorFlow graph describing all gates, stages, and pipelines. The nodes that define the operations and resources in this graph are each annotated with a logical device (i.e., a label in the TensorFlow graph attached to each node). The complete graph is then distributed to all machines in the cluster. Each machine is assigned a logical device, corresponding to a local pipeline; upon startup, the machine instantiates the nodes and stage runners corresponding to its device and connects to other machines in the cluster via the network. Once the startup process is complete, the application serves client requests via a request-response mechanism (e.g., a web server).
5. Using Ptf for Bioinformatics Applications
We demonstrate the features of PTF through the construction of PTFbio, a distributed bioinformatics framework and set of applications. PTFbio combines PTF with Persona (Byma et al., 2017), a framework written in TensorFlow that enables users to construct scale-out pipelines for bioinformatics computations ranging from genomic sequencing to protein matching. Persona leverages TensorFlow’s native code execution to incorporate popular bioinformatics applications such as SNAP (Zaharia et al., 2011) and uses the Aggregate Genomic Data (AGD) data format, a new chunked column-oriented data format designed that enables scale-out processing of large genomic and proteomic datasets.
PTFbio’s use of PTF enables the construction and deployment of persistent, flexible bioinformatics pipelines as a service. While Persona benefits from the use of TensorFlow’s many features (e.g., flexible graph composition, queues, schedulers), TensorFlow’s semantics limited it to processing a single user request per invocation. This per-request instantiation prevented high startup costs (e.g., memory mapping large files and warming up buffer pools) from being amortized across multiple requests. To demonstrate the flexibility of the approach, we focus on a genomic application that:
Aligns the reads of a genomic dataset captured by a sequencing device against the reference human genome. This is a computationally-intensive process that leverages SNAP to first determine candidate locations, compute the edit distance, and determine the candidate location(s).
Sorts the resulting locations against the human genome itself, implemented as an out-of-core merge sort. The merge sort has a parallel sort phase, which writes out intermediate sorted files, and then a serial merge phase, which reads in all intermediate files to produce a sorted dataset.
Although some datasets may fit in the memory of a single machine, an out-of-core sort enables higher throughput because the sort phase may run in parallel across multiple machines.
We implement two variants of this pipeline in PTFbio. First, the baseline application, shown in Figure 2, connects three serial pipelines together: first to align the individual reads (which generates an additional AGD column with the alignment information), then separately to sort the AGD chunks in large batches, and finally to perform the final merge stage to generate the full genomic dataset aligned and sorted against the reference genome. Each pipeline consists of multiple stages to overlap I/O phases with computational phases. It is a persistent service that is analogous to Persona’s solution of executing successive, distinct batch jobs to first align and subsequently sort a dataset using a two-phase out-of-core merge sort.
Figure 3 illustrates the enhanced solution, which fuses the alignment step with the sorting step: rather than writing the alignment column to disk and then sorting, the fused align-sort phase aligns and sorts partitions in the same local pipeline. The sort stage uses an aggregate dequeue operation to sort up to AGD chunks in memory and write out the sorted result (a single, aggregate AGD chunk per input chunks) to disk. In effect, the fused align-sort uses spare memory capacity and NIC bandwidth on the alignment machines to eliminate one full I/O read and write cycle for the dataset in addition to the associated CPU resources for compression in the baseline version.
Both variants of the pipeline limit the number of open batches in the global and local pipelines via global and local credit links. The global credit links are end-to-end, limiting the total number of open batches in the pipeline at any given time. Local credit links bound memory usage of a local pipeline. For example, the local credit link in the merge pipeline of Figure 3 prevents the read stages from reading more chunk files than the merge stages can handle, thereby limiting the amount of memory consumed by buffers receiving the data from the storage system.
Figure 3 also illustrates how PTFbio uses PTF’s abstractions and mechanisms: (1) The application consists of two serially-connected pipelines, each of which has a distinct, configurable, scale-out width to take advantage of the scale-out cluster. (2) The use of metadata tags allows for the concurrent, isolated execution of multiple batches. For example, the inherently serial dependency between the two pipelines and the serial nature of the merge phase of the out-of-core merge sort provide a key opportunity for throughput improvements without any impact on latency. (3) The use of credit-based flow-control is used both for admission control at the front of the pipeline (to control the degree of batch concurrency) as well as within the pipeline (to control the amount of memory consumed by the AGD chunks as they flow through the pipeline). (4) Both pipelines show a typical pattern of a central computational phase (alignment, sorting, or merging) surrounded by a read/decompress phase and a compress/writeback phase.
We next evaluate PTF’s ability to operate as a cloud computing framework through an evaluation of PTFbio. Specifically, we evaluate how it achieves the architectural goals outlined in §1 by evaluating the fused align-sort system described in §5. To do so, we begin by evaluating the performance benefit of pipelining requests in the application. Second, we evaluate the scale-out performance of the application as we increase the cluster size. Finally, we evaluate the benefits of fusing the align and sort pipelines and PTFbio’s ability to overlap I/O with computation.
Our evaluation shows that the semantics provided by PTF enable persistent streaming big-data applications, specifically:
PTF enables pipelining of parallel batches on the same pipeline until a component of the pipeline becomes saturated.
PTF scales out across multiple machines to the point of hardware saturation.
PTF overlaps I/O and compute to enable efficient resource utilization
6.1. Experimental Setup
We use a cluster of 20 typical datacenter machines, each with two Intel Xeon E5-2680v3 CPUs at 2.5GHz, 256 gigabytes of DRAM, and a 10GbE network interface. We enable hyperthreading on all 12 cores per socket, for a total 48 logical cores per machine. All machines run Ubuntu 18.04 Linux with the distribution’s default Linux kernel (4.15.0). The compute and storage are connected by a 40GbE-based IP fabric consisting of 8 top-of-rack switches and 3 spine switches.
The benchmarks read and write to a genomic database of paired-end whole human genome dataset from Illumina (Eberle et al., 2016) (Platinum dataset, ERR174324), which consists of 223 million single-end 101-base reads. Input and output files are stored in the Persona AGD format (Byma et al., 2017) with a chunk size of 100,000 (i.e., the number of records in each chunk file). We store the input datasets, intermediate files, and output datasets on a Ceph distributed object store (Weil et al., 2006) comprised of 18 nodes, each with 10 disks. PTFbio accesses Ceph objects via the RADOS API.
All experiments test the application running as a service processing parallel client requests. Each request is comprised of a list of keys corresponding to the AGD chunk files for a dataset. Each dataset represents a single-end dataset of one entire individual from the Illumina Platinum dataset.
The latency for each request is defined as the service time of a request once it is submitted to the pipeline. The throughput is measured as the number of bases (in millions, i.e., megabases) processed per second.
All local pipelines configure a sufficient number of stages such that a local resource is saturated (CPU, NIC, or main memory). Any additional stages do not increase performance, as all stages are executed by the TensorFlow runtime using a fixed-size thread pool per machine. Each additional stage replica specifies the maximum possible parallelism for a given stage, but the TensorFlow runtime decides which nodes amongst all stages to execute based on feed availability.
6.2. Benefits of Pipelining
Figure 4 shows the effects of the number of open batches on the throughput and latency for the fused align-sort application. The results show that each additional open batch increases overall throughput until a hardware component becomes saturated. After this point of saturation, additional open batches must queue in the buffer of the upstream gate to await processing.
This result validates the benefits of request (i.e., batch) concurrency and feed pipelining. PTF is able to coordinate the additional parallelism of processing feeds from multiple concurrent batches to better utilize the cluster’s hardware resources. This results in additional throughput with negligible or no latency increase until one component becomes saturated (i.e., the merge pipelines). PTF is able to maintain this post-saturation throughput by buffering batches at the global pipeline level.
With 6 open batches, the configuration with 3 merge pipelines is able to achieve 321 megabases/second in its maximal configuration (i.e., 17 fused align-sort pipelines), an increase of 4 over the 1 fused align-sort pipeline configuration with a 0.13 increase in request latency.
Figure 5 shows complementary CDF of latencies within the fused align-sort application from an experiment with this maximal configuration. This figure shows the end-to-end request latency as well as the latencies for the merge local pipelines for a 15-minute duration of the PTFbio operating at a steady state. Each request requires 2236 align operations, 224 sort operations (due to the grouping factor of 10 in the batching dequeue preceding the sort stage), and a single merge operation. The mean latencies for the align, sort, and merge phases is 2.7 seconds, 2.7 seconds, and 322.6 seconds, respectively.
Figure 5 confirms that (1) PTF reduces the serial latency by overlapping different phases of the application across parallel local pipelines; (2) the flow-control and scheduling mechanisms of PTF minimize tail latencies well up to the percentile; (3) the end-to-end request latency shows greater variability than the component latencies, and is the result of the combined effects of barrier delays and out-of-order feed delivery of concurrent requests. Nevertheless, the mean request latency is 420.6 seconds but the percentile is only 479.7 seconds.
6.3. Scale-Out Performance
Figure 8 demonstrates that PTF can take advantage of additional cluster nodes to both increase the overall throughput and reduce the processing latency of any request processed by the pipeline. In each series, we fix the number of local merge pipelines and open batches (sufficient to saturate the merge pipelines) and scale the number of fused align-sort local pipelines.
Figure (a)a demonstrates the scale-out behavior of the fused align-sort application’s throughput, showing that PTF is able to effectively saturate the hardware resources of a balanced pipeline. The application scales linearly across the hardware resources to the point of saturating one phase of the application. The results show that approximately 4 aligner nodes saturate one merge node.
Figure (b)b shows the effects of the scale-out behavior on latency. As the pipeline can dedicate all aligner nodes in parallel to a single batch, the latency decreases according to Amdahl’s law (Amdahl, 1967), with the remaining latency due to the merge stage. The latency of a local merge pipeline to merge and compress one dataset is an average of 298 seconds, excluding I/O, for all configurations.
6.4. Benefits of Fusing Align and Sort
The fused align-sort application enables the user to configure fewer machines and incur less I/O compared to the baseline application. Specifically, the fusion leads to a balanced use of each cluster node’s compute and I/O resources, whereas the baseline pipeline has a mix of nodes that are either CPU-bound (the aligners) or I/O-bound (the sort nodes).
Both the fused align-sort and the baseline’s align-only local pipelines are bound by the align stage. The sort stage is relatively inexpensive and takes advantage of the fact that the data is already read and decompressed into buffers to perform the alignment operation: a tuned configuration dedicates 47 aligner threads in the align-only case and 45 threads in the fused align-sort case. The minor reduction in throughput of the node is more than compensated by the reduction of 12% in aggregate I/O and the elimination of dedicated sort nodes. Furthermore, fusing aligning and sorting leads to balanced use of CPU and NIC resources of each node of the cluster.
Figure 11 shows the steady-state aggregate throughput and I/O of the fused align-sort application. These figures demonstrate that PTF enables PTFbio to overlap I/O and compute throughout the pipeline. The I/O rate shown in Figure (b)b shows the aggregate I/O rate measured at the NIC; the aggregate is computed across all local pipelines of the same type. The application throughput shown in Figure (a)a shows the aggregate throughput of the computationally-intensive parts of the local pipeline.
External vs. Internal Control: With the addition of metadata to each feed, PTF pipelines perform both data processing and control functionality of a cloud computing framework. Due to TensorFlow’s design decisions outlined in §2.2 and the dataflow rules enforced by the TensorFlow runtime, other cloud computing applications of TensorFlow have typically invoked TensorFlow graphs as a subcomponent of a larger cloud computing framework. For example, TensorFlowOnSpark (Yahoo Inc., ) invokes TensorFlow graphs as a subcomponent of a Spark (Zaharia et al., 2012) application. This combination of using TensorFlow for processing the data associated with incoming batches while delegating scheduling and controller responsibilities to an external framework is pragmatic, but it comes at a high cost: transforming data to and from TensorFlow’s internal data representation is an expensive operation, dominating the runtime of numerically intensive applications such as machine learning (Palkar et al., 2017). By attaching metadata to each feed with minimal modifications to TensorFlow (and none to the core TensorFlow runtime), PTF can process each batch by itself, without relying on an external framework.
Parameter Tuning: Tuning the parameters in a PTF pipeline is important to maximize application throughput while avoiding excessive resource usage. A properly configured pipeline will be bound by the throughput of a hardware resource (e.g., the CPU required for the align stage of PTFbio) while avoiding excessive resource usage; excessive resource usage occurs when a stage and gate upstream of the hardware-bound stage in the pipeline is not bounded, e.g., if excess buffers are used in a read or decompression stage upstream of the align stage. The key parameters to tune are (1) the number of stages within a local pipeline, (2) the number of local pipelines to replicate for each phase (for PTFbio: align, sort, align-sort, and merge) (3) the number of open batches to allow within a local or global pipeline (limited by one or more credit links). We observe the state of an application using hardware statistics (e.g., CPU and memory usage per local pipeline), tracing to record events during an execution of an application (e.g., when a read or write stage executes), and the capacity and buffer size of each gate using the Tensorboard mechanisms from TensorFlow. In practice, one scales the stages in a local pipeline until a hardware resource is saturated and then balances the number of machines allocated to each local pipeline such that the aggregate throughputs of all local pipelines are approximately equal.
Compatibility with TensorFlow:
In practice, a TensorFlow application consists of the interaction between a declarative graph and a client program. The TensorFlow client program of a typical supervised machine-learning pattern repeatedly feeds training examples to the graph and uses gradient descent to backpropagate updates to the model. The algorithm terminates after prediction error falls below a threshold or a fixed number of training examples are processed.
While PTF does not have the concept of a client program, PTF gates provide a mechanism to encode commonly-used patterns within the PTF pipeline. PTF supports supervised training of a machine learning model, feeding multiple batches of training examples against the model within the pipeline. New gates can extend PTF’s functionality to support this use case (see the aggregate dequeue operation in §3.2). We leave the evaluation of such gates to future work.
Comparison to TensorFlow loops: TensorFlow has a loop construct (Yu et al., 2018), which can be used to construct an execution pipeline that iterates across an aggregate feed containing all feeds of a given batch. While this allows concurrent execution and I/O overlap, batches must be statically partitioned across machines. PTF enables dynamic workload partitioning, provides a built-in flow-control mechanism that limits resource usage, and allows for the online submission of a stream of batches. In addition, TensorFlow loops can be naturally used within the stage graph of a PTF pipeline, e.g., to dynamically change the computation based on the value within a feed.
Fault tolerance: PTF inherits TensorFlow’s fault tolerance semantics because it does not alter the TensorFlow runtime. TensorFlow does not implement fine-grained recovery, instead relying on coarse-grained checkpointing to periodically save the state of training models; TensorFlow does not include feed-level fault recovery due to the high overhead. PTF currently relies on the exactly-once semantics of feed delivery from TensorFlow; it can relax this requirement to at-least-once semantics with additional components added to the metadata. For example, an additional feed ID can be inserted into the existing metadata tensor to differentiate each feed within a batch, effectively creating a compound ID (for both the batch and the feed) that uniquely identifies the feed between any pair of adjacent gates. PTF will inherit any feed-level recovery mechanism from TensorFlow; efforts in this regard are orthogonal and complementary to PTF.
8. Related Work
PTF builds on a multitude of related work.
Dataflow: PTF’s use of metadata to differentiate feeds of concurrent batches is inspired by the tagged token dataflow (TTDF) architecture (Arvind and Nikhil, 1990). TensorFlow incorporates many principles from TTDF, primarily using a runtime tag to associate related tensors of a given feed when concurrently processing multiple feeds. PTF uses an explicit tag, i.e., metadata, to relate different feeds across successive invocations of a graph.
Persona: PTFbio builds upon Persona (Byma et al., 2017), which consists of both a library of TensorFlow nodes for bioinformatics processing and a corresponding application (written in Python) that uses the library code to build applications that process a single request. PTF is independent of Persona; PTFbio depends on both PTF and Persona. We use the library components of Persona in developing PTFbio (e.g., I/O, alignment, compression), but rewrite PTFbio as a new application around PTF due to the single-request design of its applications. This is due to the differing goals of Persona and this work: Persona creates high-performance bioinformatics applications while PTF creates high-performance cloud computing streaming applications. We use Persona’s library to combine these two goals by developing PTFbio as an application for streaming bioinformatics pipelines that are capable of running as persistent services using PTF’s unique features.
Batching cloud computing frameworks: MapReduce (Dean and Ghemawat, 2008) is the first modern BSP-style (Valiant, 1990) framework to be used for cloud computing applications. Dryad (Isard et al., 2007) extends this architecture to support more general-purpose dataflow applications. Spark (Zaharia et al., 2012) improves the performance of these operations by introducing the Resilient Distributed Dataset, which incrementally caches datasets in memory across machines. All frameworks use a coordinator to schedule tasks between distinct stages. This coordination provides a convenient location to apply cluster scheduling and fault recovery logic. PTF eschews this model, as the scheduling overhead for multiple tasks imposes a higher latency cost for features not targeted by this work: scientific applications only require coarse grain recovery mechanisms (i.e., restarting the application) as they typically are append-only for data provenance.
Streaming cloud computing frameworks: This category of frameworks encode their logic as a dataflow graph, with each node being a long-running process that reacts to events, such as the arrival of new data on an input edge, by producing new events, such as outputting new data on an output edge. Flink (Carbone et al., 2015), StreamScope (Lin et al., 2016), and Millwheel (Akidau et al., 2013) are recent examples of this architecture. Naiad (Murray et al., 2013) extends the streaming model to include more general graphs than direct acyclic graphs, but at the cost of higher communication overhead. PTF adopts this model for execution due to its low scheduling overhead and encodes the notion of punctuations (Tucker et al., 2003) with the metadata signaling a punctuation when a request has been fully processed by a gate.
TensorFlow’s use in the cloud computing ecosystem: Several research initiatives seek to allow TensorFlow to be used as a subcomponent of a larger application in a cloud computing ecosystem. Weld (Palkar et al., 2017) unifies multiple cloud computing frameworks into a single runtime data representation, providing adapters for many existing frameworks including TensorFlow. Apache Arrow (Apache Software Foundation, ), a columnar data format for inter-framework interoperability, was recently added to Spark (Le Dem, 2017) for a similar reason. This can be combined with TensorFlowOnSpark (Yahoo Inc., ) to distribute training via Spark RDDs with low overhead (Karau, 2018). These efforts are complementary to PTF: interoperability with other frameworks with lower overhead benefits all.
Native execution: Nimbus (Mashayekhi et al., 2017) overcomes the limitations imposed by JVM-based frameworks by implementing a native dataflow engine in C++ and caching scheduling decisions through the use of execution templates. Both Nimbus and PTF approach the problem of CPU-bound cloud computing tasks by implementing an alternative to the overheads imposed by the JVM. Whereas Nimbus combines the application logic and runtime into a single binary for the worker nodes in its architecture, PTF decouples the runtime and application logic; instead of distributing a binary with the application logic, PTF sends only a serialized description of the application graph to each machine.
This work demonstrates that by introducing a few careful abstractions into TensorFlow (i.e., stages and gates), PTF can operate as a framework for constructing a wider variety of cloud computing applications and running these applications on a scale-out cluster of machines. PTF augments TensorFlow’s existing runtime and library of nodes to enable the creation of scientific cloud computing applications that operate as a service, running indefinitely while concurrently processing multiple requests. PTF serves as both the data processing and controller components of such a framework without relying on an external agent to coordinate computation: stages partition the application’s graph into independent components for processing, gates control and coordinate the progress of concurrent requests between stages, and pipelines describe sequences of stages and gates that span multiple machines.
We implement the extension in PTF and use it to develop PTFbio, a streaming bioinformatics pipeline built with components from Persona. When scaled across 20 machines, PTFbio is able to align and sort 321 megabases/second while pipelining 6 open requests in parallel. We use PTF to partition and join requests between global and local pipelines to develop a fused version of the standard align-sort-merge pipeline, eliminating an I/O phase between alignment and the first phase of sorting by combining both pipelines on a single machine. This saves a total of 12% of data transfers to the storage subsystem.
- A computational model for tensorflow: an introduction. In Proceedings of the 1st ACM SIGPLAN International Workshop on Machine Learning and Programming Languages, MAPL 2017, New York, NY, USA, pp. 1–7. External Links: Cited by: §2.2, §3.6.
- MillWheel: Fault-Tolerant Stream Processing at Internet Scale.. PVLDB 6 (11), pp. 1033–1044. Cited by: §2.1, §8.
- The Dataflow Model: A Practical Approach to Balancing Correctness, Latency, and Cost in Massive-Scale, Unbounded, Out-of-Order Data Processing.. PVLDB 8 (12), pp. 1792–1803. Cited by: §2.1.
-  Amazon Kinesis. Note: https://aws.amazon.com/kinesis/ Cited by: §2.1.
- Validity of the single processor approach to achieving large scale computing capabilities.. In AFIPS Spring Joint Computing Conference, pp. 483–485. Cited by: §6.3.
-  Apache Samza. Note: http://samza.apache.org/ Cited by: §2.1.
-  Apache Arrow. Note: https://arrow.apache.org/ Cited by: §8.
- Executing a Program on the MIT Tagged-Token Dataflow Architecture.. IEEE Trans. Computers 39 (3), pp. 300–318. Cited by: §2.2, §8.
- Petascale Computational Systems.. IEEE Computer 39 (1), pp. 110–112. Cited by: §1.
That’s Data Science: Airbus Puts 10,000 Sensors in Every Single Wing!. Note: https://www.datasciencecentral.com/profiles/blogs/that-s-data-science-airbus-puts-10-000-sensors-in-every-single Cited by: §1.
- Big Data Approaches for the Analysis of Large-Scale fMRI Data Using Apache Spark and GPU Processing: A Demonstration on Resting-State fMRI Data from the Human Connectome Project. Front Neurosci 9, pp. 492. Cited by: §1.
- Kubernetes and the path to cloud native.. In socc15, pp. 167. Cited by: §2.1.
- Persona: A High-Performance Bioinformatics Framework.. In usenix17, pp. 153–165. Cited by: 3rd item, §5, §6.1, §8.
- Apache Flink™: Stream and Batch Processing in a Single Engine.. IEEE Data Eng. Bull. 38 (4), pp. 28–38. Cited by: §2.1, §8.
- Processing: What to record?. Note: https://cds.cern.ch/record/1997399 Cited by: §1.
- FlumeJava: easy, efficient data-parallel pipelines.. In pldi10, pp. 363–375. Cited by: §1, §2.1.
- Benchmarking Streaming Computation Engines: Storm, Flink and Spark Streaming.. In ipdps16, pp. 1789–1792. Cited by: §1.
Clinically applicable deep learning for diagnosis and referral in retinal disease. Nature Medicine. External Links: Cited by: §1.
- MapReduce: simplified data processing on large clusters.. Commun. ACM 51 (1), pp. 107–113. External Links: Cited by: §1, §2.1, §8.
The MNIST Database of Handwritten Digit Images for Machine Learning Research [Best of the Web].. IEEE Signal Process. Mag. 29 (6), pp. 141–142. Cited by: §2.2.
- A reference dataset of 5.4 million human variants validated by genetic inheritance from sequencing a three-generation 17-member pedigree. bioRxiv. External Links: Cited by: §6.1.
Dermatologist-level classification of skin cancer with deep neural networks.. Nature 542 (7639), pp. 115–118. Cited by: §1.
- A Java vs. C++ Performance Evaluation: A 3D Modeling Benchmark.. In simpar12, pp. 161–172. Cited by: §1.
- Mesos: A Platform for Fine-Grained Resource Sharing in the Data Center.. In nsdi11, Cited by: §2.1.
- Loop Recognition in C++/Java/Go/Scala. In Proceedings of Scala Days 2011, External Links: Cited by: §1.
- Dryad: distributed data-parallel programs from sequential building blocks.. In eurosys07, pp. 59–72. Cited by: §1, §2.1, §8.
- In-Datacenter Performance Analysis of a Tensor Processing Unit.. In isca17, pp. 1–12. Cited by: §1.
- Accelerating Tensorflow with Apache Arrow on Spark. Note: Databricks Spark+AI Summit Cited by: §8.
- Twitter Heron: Stream Processing at Scale.. In SIGMOD Conference, pp. 239–250. Cited by: §2.1.
- Improving Python and Spark Performance and Interoperability with Apache Arrow. Note: Databricks Spark+AI Summit Cited by: §8.
- StreamScope: Continuous Reliable Distributed Processing of Big Data Streams.. In nsdi16, pp. 439–453. Cited by: §2.1, §8.
- The Java Virtual Machine Specification. Addison-Wesley. Cited by: §1.
- A survey on deep learning in medical image analysis.. Medical Image Analysis 42, pp. 60–88. Cited by: §1.
- A decade’s perspective on dna sequencing technology. Nature 470, pp. 198 EP –. External Links: Cited by: §1.
- Scalable, Fast Cloud Computing with Execution Templates.. CoRR abs/1606.01972. Cited by: §1.
- Execution Templates: Caching Control Plane Decisions for Strong Scaling of Data Analytics.. In usenix17, pp. 513–526. Cited by: §2.1, §8.
- Naiad: a timely dataflow system.. In sosp13, pp. 439–455. Cited by: §1, §2.1, §8.
- Rethinking Data-Intensive Science Using Scalable Analytics Systems.. In SIGMOD Conference, pp. 631–646. Cited by: §1.
- Weld: Rethinking the Interface Between Data-Intensive Applications.. CoRR abs/1709.06416. Cited by: §1, §7, §8.
- Improved Techniques for Training GANs.. In nips16, pp. 2226–2234. Cited by: §1.
- Big Data Spark Solution for Functional Magnetic Resonance Imaging.. CoRR abs/1603.07064. Cited by: §1.
- Computational solutions to large-scale data management and analysis. 11, pp. 647. External Links: Cited by: §1.
- Storm@twitter.. In SIGMOD Conference, pp. 147–156. Cited by: §2.1.
- Exploiting Punctuation Semantics in Continuous Data Streams.. IEEE Trans. Knowl. Data Eng. 15 (3), pp. 555–568. Cited by: §8.
- A Bridging Model for Parallel Computation.. Commun. ACM 33 (8), pp. 103–111. Cited by: §8.
- Apache Hadoop YARN: yet another resource negotiator.. In socc13, pp. 5:1–5:16. Cited by: §2.1.
- Performance evaluation of big data frameworks for large-scale data analytics.. In bigdata16, pp. 424–431. Cited by: §1.
- Large-scale cluster management at Google with Borg.. In eurosys15, pp. 18:1–18:17. Cited by: §2.1.
- Reconstructing space-charge distorted ipm profiles with machine learning algorithms. In 9th Int. Particle Accelerator Conf.(IPAC’18), Vancouver, BC, Canada, April 29-May 4, 2018, pp. 2099–2102. External Links: Cited by: §1.
- Ceph: A Scalable, High-Performance Distributed File System.. In osdi06, pp. 307–320. Cited by: §6.1.
-  TensorFlowOnSpark. Note: https://github.com/yahoo/TensorFlowOnSpark Cited by: §7, §8.
- Dynamic control flow in large-scale machine learning.. In eurosys18, pp. 18:1–18:15. Cited by: §7.
- Faster and More Accurate Sequence Alignment with SNAP. CoRR abs/1111.5572. Cited by: §5.
- Resilient Distributed Datasets: A Fault-Tolerant Abstraction for In-Memory Cluster Computing.. In nsdi12, pp. 15–28. Cited by: §1, §2.1, §7, §8.
- Discretized streams: fault-tolerant streaming computation at scale.. In sosp13, pp. 423–438. Cited by: §2.1.