This tutorial focuses on the challenge of unleashing the full potential of heterogeneous systems. We start by giving an overview of today's heterogeneous computing hardware, existing programming models and software support to program such systems. In particular, we will introduce OpenCL as means to program heterogeneous systems. Furthermore, we introduce the main challenges of heterogeneous computing, portability, ease of programming, and support of device optimizations. Finally, we examine in detail the problem of task partitioning among heterogeneous nodes, presenting the state-of-the-art in this topic and current solutions to the problem.