Inner product of random floats written to file My goals are to make this code:


faster
more idiomatic C++


What the code does:


take an integer command-line argument N
make a vector of N random floating point values
make a matrix of N*N random floating point values
do inner product of vector * matrix
write the resulting vector to a file


Currently compiled with: g++ myFile.cpp -std=c++11 -O3

#include &lt;vector&gt;
#include &lt;fstream&gt;

const std::string outputName = "output/coutput.txt"; // the name of the file this program makes

std::ostream&amp; operator&lt;&lt; (std::ostream&amp; os, const std::vector&lt;double&gt;&amp; v)
{ // pretty-print a vector of doubles using operator&lt;&lt;
  for (auto&amp; i : v)
    i == *v.begin() ? os &lt;&lt; i : os &lt;&lt; " " &lt;&lt; i;
  return os;
}

double genRand(void)
{
  return rand() / static_cast&lt;double&gt;(RAND_MAX);
}

int main(int argc, char* argv[])
{
  // file i/o
  std::ofstream result;
  result.open(outputName, std::ios::out);

  srand(1);
  long elems = std::atol(argv[1]); // command line param
  std::vector&lt;double&gt; m(elems * elems); // (elems * elems); // actually this is a vector of length (N*N)
  std::vector&lt;double&gt; a(elems);
  std::vector&lt;double&gt; r(elems, 0); // to store the result

  for (auto i = 0; i &lt; elems; i++) // generate random vector
    a[i] = genRand();

  for (auto i = 0; i &lt; elems * elems; i++) // generate random matrix
    m[i] = genRand();

  for (auto i = 0; i &lt; m.size(); i++) { 
    auto idx = i / a.size();
    r[idx] += a[idx] * m[i];
  }

  result &lt;&lt; r &lt;&lt; std::endl; // print results
  result.close();
}
If you're going to use C++11, you should firstly look at throwing out rand, and using the newer features found in &lt;random&gt;. The setup is a bit more complex, but the distributions are generally much better statistically. Also, instead of generating numbers one at a time, we're going to generate them in a batch:

template &lt;typename Cont = std::vector&lt;double&gt;&gt;
Cont generate_rand(std::size_t n)
{
    Cont results;
    results.reserve(n);

    std::random_device rd;
    std::mt19937 generator(rd());
    std::uniform_real_distribution&lt;&gt; dist;
    auto random = [&amp;]() { return dist(generator); };
    std::generate_n(std::back_inserter(results), n, random);
    return results;
}


With this, we can generate a set of random values into a vector:

// Read into num however many values we want to generate from args
auto vec = generate_rand(num);


Working with an actual matrix is a bit easier, so let's generate that (instead of an n * n length vector):

std::vector&lt;std::vector&lt;double&gt;&gt; matrix;
for(auto i = 0; i &lt; num; ++i) {
    matrix.emplace_back(generate_rand(num));
}


Something to hold our results, with the size correctly reserved:

std::vector&lt;double&gt; result;
result.reserve(num);


The algorithm library already has a function that will do what you want: std::inner_product:

for(auto it = matrix.begin(); it != matrix.end(); ++it) {
    auto v = std::inner_product(std::begin(vec), std::end(vec), std::begin(*it), 0.0);
    result.push_back(v);
}


Alternately, this is the place where a library like Eigen comes in really handy; with the correct includes, this can be written as follows:

#include &lt;Eigen/Core&gt;

typedef Eigen::MatrixXd Dynamic2d;

int main()
{
    // Initialize num from program args
    auto x = Dynamic2d::Random(num, num);
    auto y = Dynamic2d::Random(1, num);
    auto res = y * x;
}


(Note however that Random gives a range between [-1, 1] when called like this, so you'd need to potentially do a bit of work to get that distribution back to [0, 1]). This is likely to give you the maximum performance, as libraries like Eigen have had a lot of time spent on making them highly efficient.