Q:

Why is this simple C++ OpenMP program slower with multiple threads? 

In an effort to learn OpenMP, I am running a simple C++ program with OpenMP to compute the value of pi, based on this video: https://www.youtube.com/watch?v=OuzYICZUthM
Unfortunately, my program seems to be running faster with fewer threads, and I am not sure why.  My laptop has 4 cores, so it should at least run a little faster with more than one thread. 
Here is the code:
#include <iostream>
#include <omp.h>
#define  NUM_THREADS 1
#define PAD 8
using namespace std;
static long num_steps = 100000000;
double step;

int main(){
  omp_set_num_threads(NUM_THREADS);
  double pi;
  static double sum[NUM_THREADS][PAD];
  step = 1.0/(double) num_steps;
  double x;
  double start_time = omp_get_wtime();
  int nthreads;
  #pragma omp parallel
  {
    double partial_sum = 0.0;
    int ID = omp_get_thread_num();
    int nthrds = omp_get_num_threads();
    if (ID == 0) nthreads = nthrds;
    sum[ID][0] = 0.0;
    for (int i = ID; i < num_steps; i = i+ nthrds){
      x = (i + 0.5)*step;
      sum[ID][0] += 4.0/(1.0 + x*x);
    }
  }
  double time = omp_get_wtime() - start_time;
  for (int i = 0; i < nthreads; i++){
      pi += sum[i][0]*step;
  }
  cout << pi << endl;
  cout << time*1000 << endl;
}

Can someone edify me as to why the multiple threads are taking longer than a single thread?  Looking at similar posts on this issue, it appears there are problems with people's code that caused them to run slower with multiple threads.  However, this code is based pretty much vertabim off the dude from the video, so I shouldn't be having this issue while running this code. 
Note: The program uses numerical integration to compute the value of pi.  The integral is of the function 4.0/(1+x*x) from 0 to 1, which evaluates exactly to pi. 

A:

First, I'll note that I'm unable to duplicate your results.  For me, your code runs in about 500 ms with NUM_THREADS set to 1, and about 130-140 ms with NUM_THREADS set to 4, so it's scaling about as we'd expect for a 4-core machine. 
However, that's not how I'd write the code.  I'd start by simplifying the code (quite a lot).  The primary use-case for OpenMP is code that doesn't currently do anything explicitly related to threads at all, then inserting a directive, and having it run substantially faster. 
I'd write the code to depend more on OpenMP to handle the reduction and such, ending up with something like this:
#include <iostream>
#include <omp.h>
using namespace std;
static long num_steps = 100000000;
double step;

int main() {
    double pi = 0.0;
    step = 1.0 / (double)num_steps;

    double start_time = omp_get_wtime();

#pragma omp parallel for reduction(+:pi)
    for (int i = 0; i < num_steps; ++i) {
        double x = i * step;
        pi += 4.0 / (1.0 + x * x);
    }

    pi *= step;

    double time = omp_get_wtime() - start_time;

    cout << pi << endl;
    cout << time * 1000 << endl;
}

At least for me, this runs about the same speed as your code--around 500 ms without enabling OpenMP, and around 130-140ms with OpenMP enabled.