template void parallel_partial_sum(Iterator first,Iterator last) { typedef typename Iterator::value_type value_type; struct process_chunk { void operator()(Iterator begin,Iterator last, std::future* previous_end_value, std::promise* end_value) { try { Iterator end=last; ++end; std::partial_sum(begin,end,begin); if(previous_end_value) { value_type& addend=previous_end_value->get(); *last+=addend; if(end_value) { end_value->set_value(*last); } std::for_each(begin,last,[addend](value_type& item) { item+=addend; }); } else if(end_value) { end_value->set_value(*last); } } catch(...) { if(end_value) { end_value->set_exception(std::current_exception()); } else { throw; } } } }; unsigned long const length=std::distance(first,last); if(!length) return last; unsigned long const min_per_thread=25; unsigned long const max_threads= (length+min_per_thread-1)/min_per_thread; unsigned long const hardware_threads= std::thread::hardware_concurrency(); unsigned long const num_threads= std::min(hardware_threads!=0?hardware_threads:2,max_threads); unsigned long const block_size=length/num_threads; typedef typename Iterator::value_type value_type; std::vector threads(num_threads-1); std::vector > end_values(num_threads-1); std::vector > previous_end_values; previous_end_values.reserve(num_threads-1); join_threads joiner(threads); Iterator block_start=first; for(unsigned long i=0;i<(num_threads-1);++i) { Iterator block_last=block_start; std::advance(block_last,block_size-1); threads[i]=std::thread(process_chunk(), block_start,block_last, (i!=0)?&previous_end_values[i-1]:0, &end_values[i]); block_start=block_last; ++block_start; previous_end_values.push_back(end_values[i].get_future()); } Iterator final_element=block_start; std::advance(final_element,std::distance(block_start,last)-1); process_chunk()(block_start,final_element, (num_threads>1)?&previous_end_values.back():0, 0); }