im struggleling with some "best practice" idea's
only posting a small piece of the code the original is very and complicated.
See below a litte test function
TEST1 runs in 5ms
TEST2 runs in 1405ms
to me TEST2 feels like the best practice but the performace diffence are so big!
in the my full code the Functions are in the Header file and the main in the source
only the function will ever be writing to the "TEST123" the Main will only read it right after it is called, the code is not running 100000 times in the full code but around 24 times, but the faster the better (inverse kinematics of a 6 Axis Robot)
What is the best way to do this?
Or is there even better ways?
Any advice is appreciated
double TEST123[12];
void TESTFUNTC1A(int ID) {
for (int x = 0; x < 12; x++) {
TEST123[x] = 1.123;
}
}
void TESTFUNTC1A() {
int64 starttimetest2 = timeSinceEpochMillisec();
vector<double> TEST125(12);
double test123456;
for (int y = 0; y < 100000; ++y) {
TESTFUNTC1A(0);
for (int x = 0; x < 12; x++) {
test123456 = TEST123[x];
}
}
std::cout << "TEST1 " << timeSinceEpochMillisec() - starttimetest2 << endl;
}
vector<double> TESTFUNTC2A(int ID) {
vector<double> TEST124(12);
for (int x = 0; x < 12; x++) {
TEST124[x] = 1.123;
}
return TEST124;
}
void TESTFUNTC2A() {
int64 starttimetest2 = timeSinceEpochMillisec();
vector<double> TEST125(12);
double test123456;
for (int y = 0; y < 100000; ++y) {
TEST125 = TESTFUNTC2A(0);
for (int x = 0; x < 12; x++) {
test123456 = TEST125[x];
}
}
std::cout << "TEST2 " << timeSinceEpochMillisec()- starttimetest2 << endl;
}
int main()
{
TESTFUNTC1A();
TESTFUNTC2A();
}
Your code has some code smell:
vector<double> TESTFUNTC2A(int ID) {
vector<double> TEST124(12);
for (int x = 0; x < 12; x++) {
TEST124[x] = 1.123;
}
return TEST124;
}
You create TEST123 with size 12 and initialize every element to 0.0. Then you overwrite it with 1.123. Why not just write vector<double> TEST124(12, 1.123);? If you need to initialize the elements to different values then you should create an empty vector, reserve the right size and then emplace_back().
void TESTFUNTC2A() {
int64 starttimetest2 = timeSinceEpochMillisec();
vector<double> TEST125(12);
double test123456;
for (int y = 0; y < 100000; ++y) {
TEST125 = TESTFUNTC2A(0);
for (int x = 0; x < 12; x++) {
test123456 = TEST125[x];
}
}
std::cout << "TEST2 " << timeSinceEpochMillisec()- starttimetest2 << endl;
}
You create TEST125 as vector with 12 elements initialized to 0.0. But then you assign it a new vector. The initial vector should be empty so you don't needlessly allocate heap memory. Also you could create a new vector inside the loop so the vector is created in-place instead of move assigned.
The size of the vector is known at compile time. Why not use std::array?
Note that the difference in time is a failure of the compiler to properly optimize the code. It's easier in TEST1 for the compiler to see that the code has no side effect so you probably get an empty loop there but not in the TEST2 case. Did you try using clang? It's a bit better at eliminating unused std::vector.
When you write your tests you should always run your loops for different number of iterations to see if the time spend increases with the number of iterations as expected. Other than plain looking at the compiler output that's the simplest way to see if your testcase is optimized away or not.
First of all, best approach does not make much sense; it normally calls for personal opinion.
Secondly, there are no eternal rules; each project must be considered individually and handled based on its constraints. If you need to work on a limited MCU - with outdated toolset and ineffective toolchain - things can be different.
But:
Having all functions defined in header means either they are template, or inline or the toolchain cannot handle multiple TU per project, or you are just doing wrong.
Global objects(more generally, static duration objects) are supposed to be avoided; they create lots of maintenance issues due to implicit couplings generated. I can not name and count them, but implicit shared reference is one of them; initialization order is another.
Next:
If you need an array with compile-time known size, std::array can be a good choice. If the size is supposed to be immutable but relatively large, const std::unique_ptr<T[]> can be considered. std::vector is good when the size is supposed to mutate during runtime; such size mutations can be runtime costly. Raw arrays are not value types; they can't be directly transferred by-value across function boundaries: you'll need to wrap them in struct to make them by-value and that is part of what std::array does.
Related
its my first time dealing with large numbers or arrays and i cant avoid over stacking i tried to use long long to try to avoid it but it shows me that the error is int main line :
CODE:
#include <iostream>
using namespace std;
int main()
{
long long n=0, city[100000], min[100000] = {10^9}, max[100000] = { 0 };
cin >> n;
for (int i = 0; i < n; i++) {
cin >> city[i];
}
for (int i = 0; i < n; i++)
{//min
for (int s = 0; s < n; s++)
{
if (city[i] != city[s])
{
if (min[i] >= abs(city[i] - city[s]))
{
min[i] = abs(city[i] - city[s]);
}
}
}
}
for (int i = 0; i < n; i++)
{//max
for (int s = 0; s < n; s++)
{
if (city[i] != city[s])
{
if (max[i] <= abs(city[i] - city[s]))
{
max[i] = abs(city[i] - city[s]);
}
}
}
}
for (int i = 0; i < n; i++) {
cout << min[i] << " " << max[i] << endl;
}
}
**ERROR:**
Severity Code Description Project File Line Suppression State
Warning C6262 Function uses '2400032' bytes of stack: exceeds /analyze:stacksize '16384'. Consider moving some data to heap.
then it opens chkstk.asm and shows error in :
test dword ptr [eax],eax ; probe page.
Small optimistic remark:
100,000 is not a large number for your computer! (you're also not dealing with that many arrays, but arrays of that size)
Error message describes what goes wrong pretty well:
You're creating arrays on your current function's "scratchpad" (the stack). That has very limited size!
This is C++, so you really should do things the (modern-ish) C++ way and avoid manually handling large data objects when you can.
So, replace
long long n=0, city[100000], min[100000] = {10^9}, max[100000] = { 0 };
with (I don't see any case where you'd want to use long long; presumably, you want a 64bit variable?)
(10^9 is "10 XOR 9", not "10 to the power of 9")
constexpr size_t size = 100000;
constexpr int64_t default_min = 1'000'000'000;
uint64_t n = 0;
std::vector<int64_t> city(size);
std::vector<int64_t> min_value(size, default_min);
std::vector<int64_t> max_value(size, 0);
Additional remarks:
Notice how I took your 100000 and your 10⁹ and made them constexpr constants? Do that! Whenever some non-zero "magic constant" appears in your code, it's a good time to ask yourself "will I ever need that value somewhere else, too?" and "Would it make sense to give this number a name explaining what it is?". And if you answer one of them with "yes": make a new constexpr constant, even just directly above where you use it! The compiler will just deal with that as if you had the literal number where you use it, it's not any extra memory, or CPU cycles, that this will cost.
Matter of fact, that's even bad! You pre-allocating not-really-large-but-still-unneccesarily-large arrays is just a bad idea. Instead, read n first, then use that n to make std::vectors of that size.
Don not using namespace std;, for multiple reasons, chief among them that now your min and max variables would shadow std::min and std::max, and if you call something, you never know whether you're actually calling what you mean to, or just the function of the same name from the std:: namespace. Instead using std::cout; using std::cin; would do for you here!
This might be beyond your current learning level (that's fine!), but
for (int i = 0; i < n; i++) {
cin >> city[i];
}
is inelegant, and with the std::vector approach, if you make your std::vector really have length n, can be written nicely as:
for (auto &value: city) {
cin >> value;
}
This will also make sure you're not accidentally reading more values than you mean when changing the length of that city storage one day.
It looks as if you're trying to find the minimum and maximum absolute distance between city values. But you do it in an incredibly inefficient way, needing multiple loops over 10⁵·10⁵=10¹⁰ iterations.
Start with the maximum distance: assume your city vector, array (whatever!) were sorted. What are the two elements with the greatest absolute distance?
If you had a sorted array/vector: how would you find the two elements with the smallest distance?
I downloaded Visual Studio and started C++ yesterday. I have now run in to a problem though. I have a super simple program that fills a large array with booleans and then counts the number of true elements. I now want to run my program for extremely large arrays (lengths of 2^33 or 2^34 preferably). I have understood that this will generate a problem with the stack overflowing and that I should allocate the array on the heap instead. I do not understand how to do this though. I have also heard that it is customary to use vectors instead of arrays but I figured that these might be slower so I stuck to arrays. What do I do to make my program run as fast as possible for large array lengths?
void makeB(bool *a, long double length)
{
for (long x = 0; x < sqrtl(length/2)+1; ++x)
{
for (long y = x; y < sqrtl(length)+1; ++y)
{
long int z = x * x + y * y;
if (z < length)
{
a[z] = true;
}
}
}
}
int main()
{
const long length = 268435457;
static bool a[length] = {};
long b = 0;
makeB(a, length);
for (long i = 0; i < length; ++i)
{
if (a[i])
{
b += 1;
}
}
printf("%ld: ", length - 1);
printf("%ld.\n", b);
char input;
cin >> input;
return 0;
}
To clarify I want to be able to increase the length variable to larger values without getting a Stack Overflow error. Fast code is also preferrable. I m also fine with using vectors if that truly is better. If it will make the cause of my confusion clearer I come from Java.
Thanks!
EDIT: First I need to point out that indeed 2^40 is way too much to expect from my system as pointed out by almost everyone, sorry about that. I feel that I could expect maybe 2^33. And secondly thanks for all the answers but what is the final consensus? Should I have a look at std::make_unique? Thanks again!
I wanted to check whether what I wrote on the programming exam was working at least. And it turned out that it was not. And I do not understand why EXACTLY it does not work.
The task was to write a program with boolean function which should return true state if 2d matrix has only one row which consist entirely of negative element.
Here is the code:
#include "stdafx.h"
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
bool cns();
const int n=5;
int a[n][n];
bool cns() {
int ts;
//!!!!
int lc; //!! I have initiated lc variable but still it does not work !!
//!!!
//standard 2d static quad matrix
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cout << "a[" << i << "][" << j << "]=" << endl;
cin >> a[i][j];
}
}
//check whether the sum of elements of the row is negative or not
for (int i = 0; i < n; i++) {
ts = 0; //temp sum
for (int j = 0; j < n; j++) {
ts += a[i][j]; //I thought what if sum of elements is negative then the whole row is negative too
if (ts < 0) { //I have just realized that is wrong
lc++; //counter of negative lines, which consist entirely of negative elements
}
}
}
//only one row should be whole negative
if (lc == 1) {
return true;
}
else {
return false;
}
}
int main()
{
int lc;
cout << cns << endl;
return 0;
}
So could you tell me please where I did mistake with variable 'lc' and why compiler tells me "uninitialized local variable 'lc' used"?
You haven't initialized lc, but declared it.
To initialize a variable means giving it an initial value (which you should always do):
int lc = 0;
Initialising a variable is, essentially, giving it an initial value.
Your definition of lc
int lc;
does not initialise it. Since it is a variable of automatic storage duration (i.e. it is local to a block), it is not initialised.
Accessing its value therefore gives undefined behaviour.
The first thing that the code does with lc (within the first set of loops in your code) is
lc++;
Incrementing a variable of type int requires accessing its value, before producing an effect (doing the act of incrementing). Hence undefined behaviour.
The compiler warning is being issued because of that. To eliminate the warning, either initialise it where it is defined. For example;
int lc = 42;
or ensure the first operation is to set it to a valid value
int lc;
// later on the first thing ever done to lc is ...
lc = 47;
People often assume that all variables (of basic types, like int) which are defined without being explicitly initialised will have an initial value of 0 (zero). That is true in some other languages, but not in C++ - at least not in this context (an int of static storage duration IS zero-initialised).
Initialization is not what you have done here. As stated by amc176 you have only declared it.
When you declare variable lc, memory is reserved on the stack. The amount of memory reserved depends on the data type (a char will take up more memory than an int).
However, if you do not provide an initial value for that variable (i.e. initialize it) the initial value of the data type will be exactly what was present in that specific piece of memory. That is why your compiler is complaining.
I am a beginner to C++ syntax. Now, I need to create an mxn 2D array in C++ to use it in another project. I have looked at other answers which involve using tools like vector, etc. Many tools are not working on my Visual Studio 15 i.e. for vector I can not define with std::vector without a message like vector is not in std. So, I have wrote the following code:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int i; int j; int row[5][10] = {};
for (int j = 0; j < 10;)
for (int i = 0; i < 5;)
{
row[i][j] = 500;
int printf(row[i][j]);
i++;
j++;
cout << "Array:" << row[i][j] << endl;
}
return 0;
}
Surely, this is not the correct syntax. So the output is beyond my expectation. I want to create an m*n array with all the elements being the same integer; 500 in this case. That is, if m=3, n=2, I should get
500 500 500
500 500 500
There's a couple things wrong with your current code.
The first for loop is missing curly brackets
You're redefining int i and int j in your for loop. Not a complilation issue but still an issue.
You're using printf incorrectly. printf is used to output strings to the console. The correct line would be printf("%d", row[i][j]);
If you want to use a vector, you have to include it using #include <vector>. You can use a vector very similar to an array, but you don't have to worry about size.
You seem to be learning. So, I did minimal correctios to make it work. I suggest you to make modifications as per your needs.
#include <iostream>
using namespace std;
int main()
{
int row[5][10] = {};
for (int j = 0; j < 10; j++) {
for (int i = 0; i < 5; i++) {
row[i][j] = 500;
cout << row[i][j] << " ";
}
cout << endl;
}
return 0;
}
Care and feeding of std::vector using OP's program as an example.
#include <iostream>
#include <vector> // needed to get the code that makes the vector work
int main()
{
int m, n; // declare m and n to hold the dimensions of the vector
if (std::cin >> m >> n) // get m and n from user
{ // m and n are good we can continue. Well sort of good. The user could
// type insane numbers that will explode the vector, but at least they
// are numbers.
// Always test ALL user input before you use it. Users are malicious
// and incompetent <expletive delteted>s, so never trust them.
// That said, input validation is a long topic and out of scope for this
// answer, so I'm going to let trapping bad numbers pass in the interests
// of keeping it simple
// declare row as a vector of vectors
std::vector<std::vector<int>> row(m, std::vector<int> (n, 500));
// breaking this down:
// std::vector<std::vector<int>> row
// row is a vector of vectors of ints
// row(m, std::vector<int> (n, 500));
// row's outer vector is m std::vector<int>s constructed with
// n ints all set to 500
for (int j = 0; j < n; j++) // note: j++ has been moved here. This is
// exactly what the third part of a for
// statement is for. Less surprises for
// everyone this way
// note to purists. I'm ignoring the possible advantages of ++j because
// explaining them would muddy the answer.
// Another note: This will output the transverse of row because of the
// ordering of i and j;
{
for (int i = 0; i < m; i++) // ditto I++ here
{
// there is no need to assign anything here. The vector did
// it for us
std::cout << " " << row[i][j]; // moved the line ending so that
// the line isn't ended with
// every column
}
std::cout << '\n'; // end the line on the end of a row
// Note: I also changed the type of line ending. endl ends the line
// AND writes the contents of the output stream to whatever media
// the stream represents (in this case the console) rather than
// buffering the stream and writing at a more opportune time. Too
// much endl can be a performance killer, so use it sparingly and
// almost certainly not in a loop
}
std::cout << std::endl; // ending the line again to demonstrate a better
// placement of endl. The stream is only forced
// to flush once, right at the end of the
// program
// even this may be redundant as the stream will
// flush when the program exits, assuming the
// program does not crash on exit.
}
else
{ // let the use know the input was not accepted. Prompt feedback is good
// otherwise the user may assume everything worked, or in the case of a
// long program, assume that it crashed or is misbehaving and terminate
// the program.
std::cout << "Bad input. Program exiting" << std::endl;
}
return 0;
}
One performance note a vector of vectors does not provide one long block of memory. It provides M+1 blocks of memory that may be anywhere in storage. Normally when a modern CPU reads a value from memory, it also reads values around it off the assumption that if you want the item at location X, you'll probably want the value at location X+1 shortly after. This allows the CPU to load up, "cache", many values at once. This doesn't work if you have to jump around through memory. This means the CPU may find itself spending more time retrieving parts of a vector of vectors than it does processing a vector of vectors. The typical solution is to fake a 2D data structure with a 1D structure and perform the 2D to 1D mapping yourself.
So:
std::vector<int> row(m*n, 500);
Much nicer looking, yes? Access looks a bit uglier, though
std::cout << " " << row[i * n + j];
Fun thing is, the work done behind the scenes converting row[j][i] to a memory address is almost identical to row[j*n+i] so even though you show more work, it doesn't take any longer. Add to this the benefits you get from the CPU successfully predicting and reading ahead and your program is often vastly faster.
I've been tasked to create a function that identifies the number of occurrences in an array, however i am not getting the correct result. This is the function i wrote, i left out the rest of the program as that works.
int countOccurences(int b[], int size, int x)
{
int occ = x;
for(int i = 0; i < size; i++)
{
if(b[i] == occ)
occ++;
}
cout << occ << endl;
return occ;
}
If occ is meant to be the number of occurrences, it should be initialised to zero rather than x.
And the comparison should be between b[i] and x, not b[i] and occ.
And, as an aside (not affecting your actual logic), it's also very unusual to actually print out the return value in a utility function which is obviously meant to simply return the count but it may be you have that in there just for debug purposes.
And you should both ensure your indentation and use of braces is consistent between your for and your if - it will make your code easier to maintain.
That's all totally aside from the fact that C++ possesses a std::count() method in <algorithm> that will work this out for you without having to write a function to do it (although it may be that this is an educational question and the intent is to learn how to code things like this, rather than use readily made library functions to do the heavy lifting for you).
int countOccurences(int b[], const unsigned int size, const int x)
{
int occ = 0;
for(unsigned int i = 0; i < size; i++)
{
if(b[i] == x)
{
occ++;
}
}
std::cout << occ << std::endl;
return occ;
}
occ should start at zero
You should compare b[i] to x
Array indices should be unsigned
Why not be const-correct?
using namespace std; is bad practice