Why is this C++ program slower than Node.js equivalent? - c++

I'm learning C++ and decided to remake an old Node.js program to see how much faster it would be, as C++ should to my knowledge be a lot faster due to being compiled.
This program is very simple, it is just to find prime numbers. It uses the exact same logic as my Node.js program, but it takes 8 to 9 seconds whereas the Node.js took only 4 to 5 seconds.
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
// Declare functions
int main();
bool isPrime(int num);
bool is6n_1(int num);
// Define variables
int currentNum = 5; // Start at 5 so we iterate over odd numbers, we add 2 and 3 manually
int primesToFind = 1000000;
int primesFound = 2;
int* primes = NULL;
// Main
int main() {
// Create dynamic memory primes array
primes = new int[1000000];
primes[0] = 2;
primes[1] = 3;
cout << "Finding primes..." << endl;
time_t start_time = time(NULL);
// Main execution loop
for (; primesFound < primesToFind; currentNum += 2) {
if (isPrime(currentNum)) {
primes[primesFound] = currentNum;
primesFound++;
}
}
time_t end_time = time(NULL);
cout << "Finished" << endl;
cout << end_time - start_time << endl;
return 0;
}
// Check whether a number is prime
// Dependant on primes[]
bool isPrime(int num) {
// We divide it by every previous prime number smaller than the sqrt
// and check the remainder
for (int i = 1; i <= sqrt(num) && i < primesFound; i++) { // Start i at 1 to skip the first unnecessary modulo with 2
if (num % primes[i] == 0) { // because we increment by 2
return false;
}
}
return true;
}
Because I'm so new at C++ I don't know if this is due to inefficient code (probably) or because of some settings in the compiler or in Visual Studio IDE.
I'm using Visual Studio 2019 community, release version and x64 architecture with O2 optimization.
How can I make this program faster?

Regarding compiler settings, I can only say:
Use x64, not x86 (32-bit) as a target
Use Release as configuration, not Debug
Enable aggressive optimizations
(Edit) It seems you already have these settings in the compiler, so there should be nothing obvious left to do regarding the compiler.
Also, there is probably a lot of optimization possible, because it does not seem that you are using the Sieve of Eratosthenes. You can then further skip all multiples of two, and increase the step size to tree.
And you would of course have to provide the node.js code. I am almost certain that it does not use the exact same logic.

Related

Why is using all numbers to test for a prime number faster than using prime numbers only

I made this program for generating prime numbers. I know there are lots of formulas for generating them 100x faster, but this is what I did.
I tried to divide i with all numbers under i. That was the simplest method, but I though it was inefficient, since after dividing by 2 you don't need to divide by 4 and so on.
I made a list of prime numbers smaller than i, and divided i by that list's numbers. I went through the list using std::iterator, because I saw it being used in all stackoverflow answers and other tutorials. It turned out to be a lot slower. Like it took 22 seconds instead of 2.
I tried to use an int to go through the list, and it took 2 seconds again.
Next, I used 1 000 000 to see the difference between method 1 and 3. To my amazement method 1 was faster. Why is that? Shouldn't using only prime numbers to test be faster than using all numbers?
#include <iostream>
#include <vector>
#include <chrono>
int main()
{
std::cout << "how high do you want to generate prime numbers? ";
int x;
// typed 1 000 000
std::cin >> x;
auto starttime = std::chrono::high_resolution_clock::now();
std::vector<unsigned int> primes;
bool isPrime;
for (int i = 2; i <= x; ++i) {
isPrime = true;
// takes 293 seconds
//for (int div{ 2 }; div < i; ++div) {
// if ((i % div) == 0) {
// takes really really long
//for (std::vector<unsigned int>::iterator div = primes.begin(); div != primes.end(); ++div) {
//if ((i % *div) == 0) {
// takes 356 seconds
for (int iter = 0; iter < primes.size(); ++iter) {
if ((i % primes[iter]) == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
primes.push_back(i);
std::cout << i << " ";
}
}
std::cout << "generating prime numbers up to " << x << " took " <<
round(static_cast<std::chrono::duration<double>>((std::chrono::high_resolution_clock::now() - starttime)).count())
<< " seconds.";
}
its because of usage vector<unsinged int> for third method.
especially primes.push_back which leads to allocations. Try to primes.reserve initially
I'd say the main issue is that most frequently a number is divisible by 2 and thus it isn't prime. I suppose the first method is more friendly with compiler and cache. But it is hard to tell for sure. Also, try to remove printing and test for time spent. Printing tends to slow the code a lot depending on usage.
A standart method for determining all prime numbers (there are more efficient ones but this one is fairly simple).
Create vector A of boolean that will indicate whether the number is prime or not. But at start set all variables to true - except A[0]=A[1]=false.
Run for loop from i = 2 to x. If A[i] is false then skip it - i is not prime. If A[i] is true then i is prime and set all A[i*k] to false for all 1<k<x/i.
This should be more efficient either of the methods.

combinatorial exercise in C++ seeing speed decrement vs VBA

just for recreation I thought I'd model a combinatorial problem with a monte carlo implementation. I did an implementation in VBA, and then as an exercise I thought I'd try and write it in C++ (am a complete novice) to check speed differences etc. Other than my not knowing advanced coding techniques/tricks, I had naively thought that as long as the model was faithfully transferred to C++ with mirroring functions / loops / variable types as far as possible etc that other than for minor tweaks the power of C++ would give me an immediate speed improvement as am running a lot of sims with lots of embedded sorting etc. Well, quite the opposite is occurring so, so there must be something seriously wrong with the C++ implementation, which is about half as fast at best depending on parameters. They both converge to the same answer so am happy mathematically that they work.
The problem:
Suppose you have N days in which to allocate k exams randomly with, eg 2 exam slots per day (AM/PM). What is the probability that say 2 days are full exam days? I think I have a closed form for this which I believe for now, so anyway wanted to test with MC.
Algorithm Heuristic:
Quite simply, say we have 18 days, 6 exams, 2 slots a day, and we want to know the probability we'll have 2 full days.
(i) simulate 6 uniforms U_i
(ii) allocate slots to the exams by randomly allocating them amongst remaining slots using the uniforms adjusting for slots already allotted. As as example if Exam 4 got allocated slot 4 in 34-slot space but 3 and 5 were already taken, then in 36-slot space Exam_4 would be allotted slot 6 (that would be the first free slot after rebasing). Have implemented this with some embedded sorting (in VB Bubblesort/quicksort has negligible diff, so far in C++ just using bubblesort).
(iii) just convert the slots into days, then count the sims that hit the target.
Phew - that's just there for background. The spirit of this is not really to optimise the algorithm, just to help me understand what I've done wrong to make it so much slower when 'mirrored' in C++!!
The Code!
// monte carlo
#include "stdafx.h"
#include"AllocateSlots.h"
#include<vector>
#include<string>
#include<iostream>
#include<cmath>
#include<ctime>
using namespace std;
int main()
{
int i, j, k, m;
int days, exams, slotsperday, filledslotsperday, targetfulldays, filleddays;
long sims, count, simctr;
cout << "Days?: ";cin >> days;
cout << "Exams?: ";cin >> exams;
cout << "Slots Per Day?: ";cin >> slotsperday;
cout << "Filled Slots?: ";cin >> filledslotsperday;
cout << "Target Full Days?: ";cin >> targetfulldays;
cout << "No. of sims?: ";cin >> sims;
system("PAUSE");
//timer
clock_t start;
start = clock();
double randomvariate;
//define intervals for remaining slots
vector <double> interval(exams);
int totalslots = (days * slotsperday);
for (k = 1; k <= exams; k++)
{
interval[k-1] = 1 / (static_cast <double> (totalslots - k + 1));
}
vector <int> slots(exams); //allocated slots
vector <int> previousslots(exams); //previously allocated slots
vector <int> slotdays(exams); //days on which slots fall
srand((int) time(0)); //generates seed on current system time
count = 0;
for (simctr = 1; simctr <= sims; simctr++)
{
vector<int> daycounts(days); //initialised at 0
for (i = 1; i <= exams;i++)
{
//rand() generates integers in [0.0,32767]
randomvariate = (static_cast <double> (rand()+1))/ (static_cast <double> (RAND_MAX+1));
j = 1;
while (j <= totalslots - i + 1)
{
if (randomvariate < j*interval[i - 1]) break;
j++;
}
slots[i - 1] = j;
}
for (i = 2; i <= exams;i++)
{
previousslots.resize(i - 1);
for (m = 1; m <= i - 1; m++)
{
previousslots[m - 1] = slots[m - 1];
}
BubbleSort(previousslots);
for (k = 1; k <= i - 1;k++)
{
if (slots[i - 1] >= previousslots[k - 1])
{
slots[i - 1]++ ;
}
}
}
//convert slots into days
for (i = 1; i <= exams;i++)
{
slotdays[i - 1] = SlottoDays(slots[i - 1], slotsperday);
}
//calculate the filled days
filleddays = 0;
for (j = 1; j <= days; j++)
{
for (k = 1; k <= exams; k++)
{
if (slotdays[k - 1] == j)
{
daycounts[j - 1]++;
}
}
if (daycounts[j - 1] == filledslotsperday)
{
filleddays++;
}
}
//check if target is hit
if (filleddays == targetfulldays)
{
count++;
}
}
cout << count << endl;
cout << "Time: " << (clock() - start) / (double)(CLOCKS_PER_SEC) << " s" << endl;
//cout << (static_cast<double>(count)) / (static_cast<double>(sims));
system("PAUSE");
return 0;
}
And the 2 ancillary functions:
#include "stdafx.h"
#include"AllocateSlots.h"
#include<iostream>
#include<cmath>
#include<vector>
using namespace std;
//returns day for a given slot
int SlottoDays(int &examslot, int &slotsperday)
{
return((examslot % slotsperday == 0) ? examslot/ slotsperday: examslot/ slotsperday + 1);
}
//BubbleSort Algorithm
vector <int> BubbleSort(vector <int> &values)
{
int i;
int j;
int tmpSort;
int N = values.size();
for (i = 0; i < N;i++)
{
for (j = i + 1; j < N; j++)
{
if (values[i] > values[j])
{
tmpSort = values[j];
values[j] = values[i];
values[i] = tmpSort;
}
}
}
return values;
}
So there it is - like I say the algorithm is common to C++ and VBA, happy to post the VBA but in the first instance just wondered if there was glaringly thing glaringly obvious in the above. Pretty much first time have done this, used vectors etc etc, unaided, self 'taught' so have definitely screwed something up even though have managed to make it run by some miracle! Be very grateful for some words of wisdom - trying to teach myself C++ with exercises like this but what I really want to get to is speed (and mathematical accuracy of course!) for much larger projects.
Fyi in my example of 18 days, 6 exams, 2 slots per day, 2 days to get filled it should converge to about 3.77%, which it does with 1mm sims in 38s in VBA and 145s in the implementation above on my duocore 2.7G i7 4GB RAM laptop on x64 windows7.
From the discussion in comments it sounds like you may be running your program in Debug mode. This turns off a number of optimisations and even generates some extra code.
To run in Release mode look for the Solution Configurations drop down in the Standard Tool Bar and use the drop down to change from Debug to Release.
Then rebuild your Solution and rerun your tests.
To explore program performance further in Visual Studio you'll want to use the Performance Profiler tool. There's a tutorial on using the Performance Profiler (including a video) on the Microsoft documentation site: Profile application performance in Visual Studio. There's also Quickstart: First look at profiling tools and a whole bunch more: all under the Profiling in Visual Studio section.

Why am I getting the same results when using random numbers in a loop? [duplicate]

This question already has answers here:
Why do I get the same result with rand() every time I compile and run? [duplicate]
(4 answers)
Closed 8 years ago.
I'm probably being blind, nut I get the same results each time I run this console application, despite using random numbers. Can anybody kindly explain where I'm going wrong? Here is the code:
#include "stdafx.h"
#include <iostream>
#include <math.h>
#include <stdio.h>
using namespace std;
bool bacteria(long mut, long chance){
bool result;
if (mut >= chance){
result = true;
}
else{
result = false;
}
return result;
}
int run = 1000000;//Number of iterations
int mutations;
int survival;
void domutation(){
mutations = 0;
survival = 0;
for (int i = 0; i < run; i++){
long x = rand() % 2;
long y = rand() % 1000000;
bool run = bacteria(x, y);
if (run == true){
mutations++;
}
else if (run == false) {
survival++;
}
}
cout << "Mutations: " << mutations << " Survivals: " << survival << endl;
}
int main(){
for (int x = 0; x < 10; x++){
domutation();
}
int wait;
cin >> wait;
}
Each individual iteration of domutation() produces a different result to the previous iteration, but each time I run the application, the results are always the same as they were the last time I ran it, e.g. the first iteration always produces 38 mutations, and the last always produces 52, and all in between are unchanged.
I'm sure I'm doing something dopey!
I am working in VS 2013 in Windows 8.1.
Thanks!
rand gives you a predictable stream of numbers. You need to seed it to choose a different point in this stream to start. Assuming you won't run your program more than once per second, the current time is a cheap/easy seed.
int main(){
srand(time(NULL));
for (int x = 0; x < 10; x++){
domutation();
}
Note that not providing a seed is equivalent to always starting your program with srand(0)

main() not executing, but compiling

I have this simple program:
// Include libraries
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// Include locals
// Start
#define NUMBER 600851475143
int main(int argc, const char* argv[])
{
long long int ans = 0;
long long int num = NUMBER;
vector<int> factors;
do
{
// Get lowest factor
for (int i = 1; i <= num; ++i)
{
if (!(num % i))
{
factors.push_back(i);
num /= i;
break;
}
}
} while (num > 1);
cout << "Calculated to 1.\n";
int highestFactor = numeric_limits<int>::min();
for (int i = 0; i < factors.size(); ++i)
{
if (factors[i] > highestFactor)
{
highestFactor = factors[i];
}
}
ans = highestFactor;
cout << ans << endl;
return EXIT_SUCCESS;
}
compiling with g++ -O2 -c -o prob3.o prob3.cpp proved successful, but when I ran it I saw nothing and it just kept running and I had to Ctrl-C (force-kill) it in the end. When I try to add
int main(int argc, const char* argv[])
{
cout << "Test\n";
to the program, Test didn't get printed too. It's like my program is not executed at all.
Any help or advice is appreciated!
Solution
I forgot prime numbers started at 2. Change for (int i = 1 to for (int i = 2.
Those nested loops are going to loop forever. The inner for loop will only ever execute once because of the break so it will only ever do num /= 1. That means num never decreases and so num > 1 will never be false. I suppose you just need to wait longer!
The reason you're not seeing "Test" is probably because you haven't flushed the output. Try:
std::cout << "Test" << std::endl;
Your program is simply running. It takes a long time to execute.
For the cout << "Test\n";, it's a matter of the cout stream not being flushed: what you wrote to the stream is still in your program memory and not yet flushed to the system to be printed.
Have you tried to start your for condition from 2? The module function doesn't have sense if start from 1.
if (!(num % i))
Num / 1 give 0, so you're not enter in the if condition
Your loop is an infinite loop. The first factor you find is 1 (since num % 1 is 0) and as such you divide num by 1 which results in num which re-enters the for loop, which does the same again and again.
Also with this fixed (initialize i in the loop with 2), your inner for loop is most likely an infinite loop and/or causing UB. Otherwise (as the others stated) it is "just" running very long. For the case where it is different (assuming most common platforms here). This depends on the value you are trying to factor, if the first factor is smaller than std::numeric_limits<int>::max() then this does not apply. Lets call those primes BIGPRIME (600851475149 would be a good example).
long long int is at least 64bit in size. int is unlikely to be bigger than 32bit on most platforms, so when it is not bigger on your platform it can only go up to std::numeric_limits<int>::max() which is (again assuming the common 32bit platform here) 2147483647 which is in turn promoted in the comparison to long long int but keeps its value, which is always smaller than BIGPRIME. Always increasing i does never get anywhere, and once you are at max() you enter UB land as signed integers don't wrap in C++. Your code might infinite loop there, or do some things like recording -1 as a valid factor, or make you pregnant.
You can easily observe that by adding some
if( 0 == (i%100000000)){ std::cout << i << std::endl; }
into the for loop.

Sieve of Eratosthenes c++ implementation error

I wrote this implementation of the Sieve of Eratosthenes in c++, but whenever the code reaches 59 (the 16th prime), it stops working. It can only reach 37 on my older machine. When I debug the program, all the variables seem to be working fine; the program simply crashes. Here it is: (I know it has a lot of comments, and lots are unnecessary.)
// Problem 7:What is the 10 001st prime number?
/*This program generates a list of prime numbers and uses the Sieve of Eratosthenes to find them.
*This is done by crossing out multiples of the first known prime (2), taking the first number
*not yet crossed out, and setting that as the next prime to "sieve" with.
*/
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int placeholder; //added at the end to prevent window from closing
const int sieve_size = 10000; //amount of #s to sieve through
const int solution_number = 10001; //# of primes to generate
long long solution; //the 10 001st prime #
long long current_sieve; //current # sieving with
int number_of_primes = 1; //we know the first prime -- 2
long long *primes = new long long [number_of_primes];
primes[0] = 2; //2 is the first prime
bool flag_havePrime = 0; //whether we have our next prime yet; used when saving a prime
bool sieve[sieve_size] = {0}; //0 is "could-be-prime" (not composite), 1 is composite.
sieve[0] = 1; //0 and 1 are not prime #s
sieve[1] = 1;
for (int i = 0; number_of_primes <= solution_number; i++) //each loop sieves with a different prime
{
current_sieve = primes[i];
//This next loop sieves through the array starting with the square of the number we will sieve with,
//this optimizes the run time of the program.
for (long long j=current_sieve*current_sieve; j <= sieve_size; j++)
if (j%current_sieve == 0) sieve[j] = 1;
/*This loop gets our next prime by looking through the array until
*it encounters a number not crossed out yet. If it encounters a prime,
*it increments the number of primes, then saves the new prime into
*primes[]. It also prints that prime (for debugging purposes).
*The "for" loop ends when it finds a prime, which it knows by encountering
*the "havePrime" flag. This needs to be reset before every run.
*/
for (long long j = primes[number_of_primes-1]+1; flag_havePrime == 0; j++)
{
if (sieve[j] == 0)
{
number_of_primes++;
primes[number_of_primes-1] = j; //because array counting starts # 0
cout << primes[number_of_primes-1] << endl; //because array counting starts # 0
flag_havePrime = 1;
}
}
flag_havePrime = 0; //resetting this flag
}
solution = primes[number_of_primes-1]; //because array counting starts # 0
delete[] primes;
primes = 0;
cout << "The 10 001st prime number is:\n";
cout << solution << endl;
cin >> placeholder;
return 0;
}
I'm thinking it could be an overflow problem?
Here's an updated snippet with only the changes:
const int sieve_size = 500000;
long long *primes = new long long [solution_number];
Debugging returns a (gasp) heap overflow though, but running the compiled version doesn't. The compiled version stops at 104759, going over by 1. That's probably easy enough to fix. But the program doesn't print the last bit, where it gives you the solution. Weird.
int number_of_primes = 1; //we know the first prime -- 2
long long *primes = new long long [number_of_primes];
This will create a one-element array. I'm pretty certain you'll need something bigger than that for storing the primes.
Specifically, as soon as you start setting values like primes[11] (for example), you're into the realm of undefined behaviour.
Perhaps there's a different variable you may want to consider using for the size in the new statement, nudge, nudge, wink, wink, a nod's as good as a wink to a blind horse :-)
There's a few other problems you also have in that code. The main one is that your sieve itself is only 10,000 elements long. The idea of a sieve is that you take a large number of things and filter out those not matching. For what it's worth, the 10,001st is a touch under 105,000 so your sieve should be at least that big.
Secondly, I've seen people use the square of a number to optimise finding of factors but not in this way:
for (long long j=current_sieve*current_sieve; j <= sieve_size; j++)
if (j%current_sieve == 0) sieve[j] = 1;
What you want is to start at double the current sieve and add it each time, something like:
for (long long j = current_sieve * 2; j < sieve_size; j += current_sieve)
sieve[j] = 1;
Here is a fixed version to compare with:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
const int sieve_size = 1 << 20;
const int solution_number = 10001;
int number_of_primes = 0;
vector<bool> sieve(sieve_size, true);
for (int i = 2; i < sieve_size; i++)
{
if (!sieve[i])
continue;
if (++number_of_primes == solution_number)
{
cout << "The 10 001st prime number is:" << i << endl;
return 0;
}
for (long long j = i*2; j < sieve_size; j += i)
sieve[j] = false;
}
}
Output:
The 10 001st prime number is:104743