Optimizing performance and reliability on heterogeneous parallel systems: Approximation algorithms and heuristics