  Many modern and emerging applications must process increasingly large volumes
of data. Unfortunately, prevalent computing paradigms are not designed to
efficiently handle such large-scale data: the energy and performance costs to
move this data between the memory subsystem and the CPU now dominate the total
costs of computation. This forces system architects and designers to
fundamentally rethink how to design computers. Processing-in-memory (PIM) is a
computing paradigm that avoids most data movement costs by bringing computation
to the data. New opportunities in modern memory systems are enabling
architectures that can perform varying degrees of processing inside the memory
subsystem. However, there are many practical system-level issues that must be
tackled to construct PIM architectures, including enabling workloads and
programmers to easily take advantage of PIM. This article examines three key
domains of work towards the practical construction and widespread adoption of
PIM architectures. First, we describe our work on systematically identifying
opportunities for PIM in real applications, and quantify potential gains for
popular emerging applications (e.g., machine learning, data analytics, genome
analysis). Second, we aim to solve several key issues on programming these
applications for PIM architectures. Third, we describe challenges that remain
for the widespread adoption of PIM.
