Speeding up calculation using vectors in C++ by using pointers/references - c++

Currently, I am making a C++ program that solves a sudoku. In order to do this, I calculate the "energy" of the sudoku (the number of faults) frequently. This calculation unfortunately takes up a lot of computation time. I think that it can be sped up significantly by using pointers and references in the calculation, but have trouble figuring out how to implement this.
In my solver class, I have a vector<vector<int> data-member called _sudoku, that contains the values of each site. Currently, when calculating the energy I call a lot of functions with pass-by-value. I tried adding a & in the arguments of the functions and a * when making the variables, but this did not work. How can I make this program run faster by using pass-by-reference?
Calculating the energy should not change the vector anyway so that would be better.
I used the CPU usage to track down 80% of the calculation time to the function where vectors are called.
int SudokuSolver::calculateEnergy() {
int energy = 243 - (rowUniques() + colUniques() + blockUniques());//count number as faults
return energy;
}
int SudokuSolver::colUniques() {
int count = 0;
for (int col = 0; col < _dim; col++) {
vector<int> colVec = _sudoku[col];
for (int i = 1; i <= _dim; i++) {
if (isUnique(colVec, i)) {
count++;
}
}
}
return count;
}
int SudokuSolver::rowUniques() {
int count = 0;
for (int row = 0; row < _dim; row++) {
vector<int> rowVec(_dim);
for (int i = 0; i < _dim; i++) {
rowVec[i] = _sudoku[i][row];
}
for (int i = 1; i <= _dim; i++) {
if (isUnique(rowVec, i)) {
count++;
}
}
}
return count;
}
int SudokuSolver::blockUniques() {
int count = 0;
for (int nBlock = 0; nBlock < _dim; nBlock++) {
vector<int> blockVec = blockMaker(nBlock);
for (int i = 1; i <= _dim; i++) {
if (isUnique(blockVec, i)) {
count++;
}
}
}
return count;
}
vector<int> SudokuSolver::blockMaker(int No) {
vector<int> block(_dim);
int xmin = 3 * (No % 3);
int ymin = 3 * (No / 3);
int col, row;
for (int i = 0; i < _dim; i++) {
col = xmin + (i % 3);
row = ymin + (i / 3);
block[i] = _sudoku[col][row];
}
return block;
}
bool SudokuSolver::isUnique(vector<int> v, int n) {
int count = 0;
for (int i = 0; i < _dim; i++) {
if (v[i] == n) {
count++;
}
}
if (count == 1) {
return true;
} else {
return false;
}
}
The specific lines that use a lot of computatation time are the ones like:
vector<int> colVec = _sudoku[col];
and every time isUnique() is called.
I expect that if I switch to using pass-by-reference, my code will speed up significantly. Could anyone help me in doing so, if that would indeed be the case?
Thanks in advance.

If you change your SudokuSolver::isUnique to take vector<int> &v, that is the only change you need to do pass-by-reference instead of pass-by-value. Passing with a pointer will be similar to passing by reference, with the difference that pointers could be re-assigned, or be NULL, while references can not.
I suspect you would see some performance increase if you are working on a sufficiently large-sized problem where you would be able to distinguish a large copy (if your problem is small, it will be difficult to see minor performance increases).
Hope this helps!

vector<int> colVec = _sudoku[col]; does copy/transfer all the elements, while const vector<int>& colVec = _sudoku[col]; would not (it only creates an alias for the right hand side).
Same with bool SudokuSolver::isUnique(vector<int> v, int n) { versus bool SudokuSolver::isUnique(const vector<int>& v, int n) {
Edited after Jesper Juhl's suggestion: The const addition makes sure that you don't change the reference contents by mistake.
Edit 2: Another thing to notice is that vector<int> rowVec(_dim); these vectors are continuously allocated and unallocated at each iteration, which might get costly. You could try something like
int SudokuSolver::rowUniques() {
int count = 0;
vector<int> rowVec(_maximumDim); // Specify maximum dimension
for (int row = 0; row < _dim; row++) {
for (int i = 0; i < _dim; i++) {
rowVec[i] = _sudoku[i][row];
}
for (int i = 1; i <= _dim; i++) {
if (isUnique(rowVec, i)) {
count++;
}
}
}
return count;
}
if that doesn't mess up with your implementation.

Related

OOP Best Way To Call Similar Functions

Background:
I have 2 similar blocks of code that I would like to merge together in a function. One block is for the x axis and the other is for the y axis. I have had this similar issue multiple times before and have shrugged it off since I assumed there was no better way of merging these in a clean fashion.
Problem:
How do I make a function that can replace both snippets of code below in the least number of lines?
Code:
//rows
vector<float> rowSpectrum;
float tempVal;
for (int i = 0; i < ROI.size().height; i++) {
tempVal = cv::mean(cleanImg.row(i)).val[0];
rowSpectrum.push_back(tempVal);
}
//columns
vector<float> colSpectrum;
for (int i = 0; i < ROI.size().width; i++) {
tempVal = cv::mean(cleanImg.col(i)).val[0];
colSpectrum.push_back(tempVal);
}
auto calcSpectrum = [&](int size, cv::Mat (cv::Mat::*memFn)(int) const) {
vector<float> spectrum;
for (int i = 0; i < size; i++) {
auto tempVal = cv::mean((cleanImg.*memFn)(i)).val[0];
spectrum.push_back(tempVal);
}
return spectrum;
}
auto rowSpectrum = calcSpectrum(ROI.size().height, &cv::Mat::row);
auto colSpectrum = calcSpectrum(ROI.size().width, &cv::Mat::col);

change my recursive solution into a dynamic programming solution

here I am trying to convert my recursive solution into a dynamic solution but I am getting problem in converting. I am trying to count minimum possible coin to make value. what I am doing is I am taking all possible coin and putting inside a vector and finally in main function I will find and minimum of my vector and that will be my answer
int rec(vector<int>coins,int n,int sum,int counter)
{
if(sum==0)
{
return 1;
}
if(n==0)
{
return 0;
}
int total=rec(coins,n-1,sum,counter);
if(sum-coins[n-1]>=0)
{
total+=rec(coins,n,sum-coins[n-1],counter+1);
if(sum-coins[n-1]==0)
{
vec.push_back(counter+1);
}
}
return total;
}
you should first try to solve this type of problems by yourself.
BTW:
#define BIG 2147483647
int min_coin(int *coins, int m, int desire_value)
{
int dp[desire_value+1];
dp[0] = 0;
for (int i=1; i<=desire_value; i++)
dp[i] = BIG;
for (int i=1; i<=desire_value; i++)
{
for (int j=0; j<m; j++)
if (coins[j] <= i)
{
int diff = dp[i-coins[j]];
if (diff != BIG && diff + 1 < dp[i])
dp[i] = diff + 1;
}
}
if(dp[desire_value]==BIG)
return -1;
return dp[desire_value];
}
you can easily convert dp and coins to vector. vector is like array.(beware for allocate vector for dp you should reserve space in vector see here.)

The most occuring number in structure(array)

I cant find out whats wrong with this part of my program, i want to find out most occuring number in my structure(array), but it finds only the last number :/
void Daugiausiai(int n)
{
int max = 0;
int sk;
for(int i = 0; i < n; i++){
int kiek = 0;
for(int j=0; j < n; j++){
if(A[i].datamet == A[j].datamet){
kiek++;
if(kiek > max){
max = kiek;
sk = A[i].datamet;
}
}
}
}
}
ps. its only a part of my code
You haven't shown us enough of your code, but it is likely that you are not looking at the real result of your function. The result, sk is local to the function and you don't return it. If you have global variable that is also named sk, it will not be touched by Daugiausiai.
In the same way, you pass the number of elements in your struct array, but work on a global struct. It is good practice to "encapsulate" functions so that they receive the data they work on as arguments and return a result. Your function should therefore pass both array length and array and return the result.
(Such an encapsulation doesn't work in all cases, but here, it has the benefit that you can use the same function for many different arrays of the same structure tape.)
It is also enough to test whether the current number of elements is more than the maximum so far after your counting loop.
Putting all this together:
struct Data {
int datamet;
};
int Daugiausiai(const struct Data A[], int n)
{
int max = 0;
int sk;
for (int i = 0; i < n; i++){
int kiek = 0;
// Count occurrences
for(int j = 0; j < n; j++){
if(A[i].datamet == A[j].datamet) kiek++;
}
// Check for maximum
if (kiek > max) {
max = kiek;
sk = A[i].datamet;
}
}
return sk;
}
And you call it like this:
struct Data A[6] = {{1}, {2}, {1}, {4}, {1}, {2}};
int n = Daugiausiai(A, 6);
printf("%d\n", n); // 1
It would be nice if you had english variable names, so I could read them a bit better ^^. What should your paramter n do? Is that the array-length? And what should yout funtion do? It has no return value or something.
int getMostOccuring(int array[], int length)
{
int current_number;
int current_count = 0;
int most_occuring_number;
int most_occuring_count = 0;
for (int i = 0; i < length; i++)
{
current_number = array[i];
current_count = 0;
for (int j = i; j < length; j++)
{
int test_number = array[j];
if (test_number == current_number)
{
current_count ++;
if (current_count > most_occuring_count)
{
most_occuring_number = current_number;
most_occuring_count = current_count;
}
}
}
}
return most_occuring_number;
}
this should work and return the most occuring number in the given array (it has a bad runtime, but is very simple and good to understand).

Vector access speed, which method is faster?

I'm curious which method is faster when accessing vectors.
For the sake of simplicity, lets say I have two objects: Player and Ship.
There's a vector of player pointers vector<Player*> players and each player object contains a vector of ship pointers vector<Ship*> ships, and then each ship has several functions that it can call, and so on.
In these situations, is it faster to access these functions directly? Or to create a temporary object pointer to access everything?
Is it faster to do this:
for (int i = 0; i < players.size(); i++)
{
for (int j = 0; j < players.at(i)->ships.size(); j++)
{
players.at(i)->ships.at(j)->update();
if (
(players.at(i)->ships.at(j)->get_x() > 0) &&
(players.at(i)->ships.at(j)->get_x() < screen_x) &&
(players.at(i)->ships.at(j)->get_y() > 0) &&
(players.at(i)->ships.at(j)->get_y() < screen_y)
)
{
players.at(i)->visible.push_back(j);
}
}
}
Or is it faster to create temporary pointers so that the vectors don't need to be continually accessed:
for (int i = 0; i < players.size(); i++)
{
Player* play = players.at(i);
for (int j = 0; j < play->ships.size(); j++)
{
Ship* ship = play->ships.at(j);
ship->update();
int ship_x = ship->get_x();
int ship_y = ship->get_y();
if (
(ship_x > 0) &&
(ship_x < screen_x) &&
(ship_y > 0) &&
(ship_y < screen_y)
)
{
play->visible.push_back(j);
}
}
}
I know the second is visually neater, but don't really know if it's necessarily faster.
Thoughts?
Seems to me that the emphasis on speed is misplaced. I think you should start by writing the code to be more readable:
auto is_visible = [=](Ship const &s) { return s.get_x() > 0 && s.get_x() < screen_x
&& s.get_y() > 0 && s.get_y() < screen_y;
};
for (auto & player : players)
std::copy_if(ships.begin(), ships.end(),
std::back_inserter(player.visible),
is_visible);
At least IMO, this is at least as safe as using at for indexing, but probably at least as fast as using [], and more readable than either one.
I should probably add one more point: visibility doesn't seem to depend on the player. At least from the way the code's written, all the players will have the same set of visible ships. If that's correct, you probably want to do something more like:
std::vector<Ship> visible;
std::copy_if(ships.begin(), ships.end(),
std::back_inserter(visible),
[=](Ship const &s) { return s.get_x() > 0 && s.get_x() < screen_x
&& s.get_y() > 0 && s.get_y() < screen_y; });
for (auto &player : players)
player.visible = visible;
You should check and see which one is faster.
It might be the first or it might be the second. It will definitely be the first if most ships' X coordinate is negative.
However, if the second one looks better to you (it does to me, too), stick with it. Worry about performance when there's an actual performance issue.
I think you're at the mercy of your optimizing compiler here. Either one might be faster, depending on how it gets optimized.
In the first version, it's possible that the compiler will decide to
pull out the players.at(i)->ships.at(j) common subexpression,
possibly with the get_x() or get_y() turning it into something
that looks a lot like your second version.
In the second version, it's possible that reordering could move the
int ship_y = ship->get_y() into the loop conditional so that it can
short circuit with ship_y > 0.
In both, it might decide to turn the entire short circuit conditional
into a sequence of fast bitwise and instructions, eliminating
branches
But my guess is that you're not going to see much difference either way. Try dumping the assembly code to compare, and of course, profile it.
Thanks for the info everyone. Since there wasn't a clear cut "option A is definitely faster than option B", I took your advice and did a bench test.
Here's some code I put together.
Basically, it creates 100 players. Each player has a vector of 100 ships. Each ship has a vector of 100 crew. (Once it ran, it consumed about 500MB of RAM).
I ran the test both unoptimized and optimized (the -O3 flag)
Test 1 was the chain pointers (ie. player->ship->crew->number, etc.)
Test 2 was the same as Test 1, but I replaced all the .at() with operator[].
Test 3 was using temporary pointers to access everything.
I ran each test multiple times and averaged the results.
Here's my results:
Unoptimized:
Test 1: 13000
Test 2: 5500
Test 3: 2800
Optimized:
Test 1: 1050
Test 2: 650
Test 3: 450
It shows that optimizing greatly increased speed in all cases.
Either way though, optimized or unoptimized, .at() definitely slows things WAY down. Using the operator[] was significantly faster.
But in the end, using a temporary pointer was the fastest in all cases.
#include <vector>
#include <ctime>
#include <iostream>
using namespace std;
class People
{
public:
vector<int> number;
};
class Ship
{
public:
Ship(int f);
vector<People*> crew;
int get_x();
int get_y();
private:
int x;
int y;
};
Ship::Ship(int f)
{
//Assign some nonsense for testing purposes
x = f * 50;
y = f * 75;
}
int Ship::get_x()
{
return x;
}
int Ship::get_y()
{
return y;
}
class Player
{
public:
vector<Ship*> ships;
};
int main(int argc, char *argv[])
{
vector<Player*> players;
int start, end;
unsigned int i, j, k, l;
//Create 100 players, each with 100 ships, and each ship with 100 crew.
for (i = 0; i < 100; i++)
{
Player* play = new Player;
players.push_back(play);
for (j = 0; j < 100; j++)
{
Ship* new_ship = new Ship(j);
play->ships.push_back(new_ship);
for (k = 0; k < 100; k++)
{
People* newbie = new People;
new_ship->crew.push_back(newbie);
for (l = 0; l < 100; l++)
{
newbie->number.push_back(0);
}
newbie->number.clear();
}
}
}
//Test 1
start = clock();
for (i = 0; i < players.size(); i++)
{
for (j = 0; j < players.at(i)->ships.size(); j++)
{
for (k = 0; k < players.at(i)->ships.at(j)->crew.size(); k++)
{
for (l = 0; l < 100; l++)
{
//Give each crew some number to hold on to.
players.at(i)->ships.at(j)->crew.at(k)->number.push_back(players.at(i)->ships.at(j)->get_x() * players.at(i)->ships.at(j)->get_y() + l);
}
//Clear the number list for the next test.
players.at(i)->ships.at(j)->crew.at(k)->number.clear();
}
}
}
end = clock();
cout << "Test 1: " << (end - start) << endl;
//Test 2
start = clock();
for (i = 0; i < players.size(); i++)
{
for (j = 0; j < players[i]->ships.size(); j++)
{
for (k = 0; k < players[i]->ships[j]->crew.size(); k++)
{
for (l = 0; l < 100; l++)
{
players[i]->ships[j]->crew[k]->number.push_back(players[i]->ships[j]->get_x() * players[i]->ships[j]->get_y() + l);
}
players[i]->ships[j]->crew[k]->number.clear();
}
}
}
end = clock();
cout << "Test 2: " << (end - start) << endl;
//Test 3
start = clock();
for (i = 0; i < players.size(); i++)
{
Player* temp_play = players.at(i);
for (j = 0; j < temp_play->ships.size(); j++)
{
Ship* temp_ship = temp_play->ships.at(j);
for (k = 0; k < temp_ship->crew.size(); k++)
{
People* temp_crew = temp_ship->crew.at(k);
for (l = 0; l < 100; l++)
{
temp_crew->number.push_back(temp_ship->get_x() * temp_ship->get_y() + l);
}
temp_crew->number.clear();
}
}
}
end = clock();
cout << "Test 3: " << (end - start) << endl;
return 0;
}

How to use selection sort algorithm correctly to sort a list?

I cannot get this to work, seems like whatever I do it never sorts correctly.
I am trying to sort in a descending order based on number of points.
Bryan_Bickell 2 5 +2
Brandon_Bolig 0 3 0
Dave_Bolland 4 2 -1
Sheldon_Brookbank 0 4 -1
Daniel_Carcillo 0 1 +3
The middle column is the amount of points.
I am using 4 arrays to store all of those values, how would I correctly utilize the array selection sort to get it to order in the right way?
I had tried all the answers below but none of them seemed to work, this is what i have so far
void sortArrays( string playerNames[], int goals[], int assists[], int rating[], int numPlayers )
{
int temp, imin;
int points[numPlayers];
for(int j = 0; j < numPlayers; j++)
{
points[j] = goals[j] + assists[j];
}
imin = points[0];
for(int i = 0; i < numPlayers; i++)
{
if (points[i] < imin)
{
imin = points[i];
}
}
for(int j = 1; j < numPlayers; j++)
{
if (points[j] > imin)
{
temp = points[j];
points[j] = points[j-1];
points[j-1] = temp;
}
}
}
it should go like this...
void selsort(int *a,int size)
{
int i,j,imin,temp;
//cnt++;
for(j=0;j<size;j++)
{
//cnt+=2;
imin=j;
for(i=j+1;i<size;i++)
{
//cnt+=2;
if(a[i]<a[imin])
{
//cnt++;
imin=i;
}
}
if(imin!=j)
{
//cnt+=3;
temp=a[j];
a[j]=a[imin];
a[imin]=temp;
}
}
}
You don't need 4 arrays to store those records if only the middle column is used for sorting, i.e, keys used for sorting the records. From my understanding, you are trying to sort those records of people based on the number of points with selection sort. Code should look like the following: assuming records is your array of records
void selectionSort(RECORD records[], int n) {
int i, j, minIndex, tmp;
for (i = 0; i < n - 1; i++) {
maxIndex = i;
for (j = i + 1; j < n; j++) //find the current max
{
if (records[j].point > records[minIndex].point)
{
//assume point is the number of point, middle column
minIndex = j;
}
}
//put current max point record at correct position
if (minIndex != i) {
tmp = records[i];
records[i] = records[minIndex];
records[minIndex] = tmp;
}
}
}
It will sort all your records in "descending order" as you want
how about store the data into a std::vector then sort it
int compare(int a, int b){
return (a>b);
}
void sort(std::vector<int> &data){
std::sort(data.begin(), data.end(), compare);
}
try to use vector as much possible, they have been heavy optimized for performance and better memory usage