So, I'm working at inventing my own tile map creation and I got a problem on size. The maximum size (which I did not set) is <700x700, anything higher makes it crash. First, I thought it's something I got wrong when making the "presentation version" which outputs the result on screen -> ScreenShot, but now I just finished making it more compact and tried using 800x800 and it still has the 7 limit, but I have no idea why. Since the code isn't that big I will show it here. If you have some tips I don't mind taking them.
#include <iostream>
#include <string.h>
#include <fstream>
#include <ctime>
#include <cstdlib>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#define _WIN32_WINNT 0x0501
#include <windows.h>
using namespace std;
int main()
{
sf::Vector2i Size;
int Points,rands,PointsCheck=1,x,y,RandX,RandY,CurrentNumber=1;
srand(time(0));
bool Done=false,Expanded,Border;
ofstream Out("txt.txt");
/***/
cout << "Size X-Y = "; cin >> Size.x >> Size.y;cout << endl;
cout << "MAX Points - " << (Size.x*Size.y)/10 << endl;
cout << "Number of POINTS = ";cin >> Points ;cout << endl;
/***/
int PixelMap[Size.x+1][Size.y+1];
/***/
for (x=1;x<=Size.x;x++) for (y=1;y<=Size.y;y++) PixelMap[x][y]=0;
/***/
while(PointsCheck<=Points)
{
rands=1+(rand()%10);
RandX=1+(rand()%(Size.x));RandY=1+(rand()%(Size.y));
if (rands==1 && PointsCheck<=Points && PixelMap[RandX][RandY]==0)
{PixelMap[RandX][RandY]=CurrentNumber;CurrentNumber+=2;PointsCheck++;}
}
/***/
while(Done==false)
{
Done=true;
for(x=1;x<=Size.x;x++)
for(y=1;y<=Size.y;y++)
if(PixelMap[x][y]%2!=0 && PixelMap[x][y]!=-1)
{
if (PixelMap[x+1][y]==0) PixelMap[x+1][y]=PixelMap[x][y]+1;
if (PixelMap[x-1][y]==0) PixelMap[x-1][y]=PixelMap[x][y]+1;
if (PixelMap[x][y+1]==0) PixelMap[x][y+1]=PixelMap[x][y]+1;
if (PixelMap[x][y-1]==0) PixelMap[x][y-1]=PixelMap[x][y]+1;
}
for(x=1;x<=Size.x;x++)
for(y=1;y<=Size.y;y++)
if(PixelMap[x][y]!=0 && PixelMap[x][y]%2==0) {PixelMap[x][y]--;Done=false;}
}
for(x=1;x<=Size.x;x++){
for(y=1;y<=Size.y;y++)
{Out << PixelMap[x][y] << " ";}Out << endl;}
//ShowWindow (GetConsoleWindow(), SW_HIDE);
}
What you have here is the concept from which this site gets its name. You have a stack overflow:
int PixelMap[Size.x+1][Size.y+1];
If you want to allocate a large amount of memory, you need to do it dynamically (on the heap).
You can do this any number of ways. Since you are using C++, I recommend using a std::vector. The only trick is making the array 2-dimensional. Usually this is done in the same way as the one you allocated on the stack, except you don't get language syntax to help you:
vector<int> PixelMap( (Size.x+1) * (Size.y+1) );
Above, you'll need to calculate the linear index from the row/column. Something like:
int someval = PixelMap[ row * (size.y+1) + column ];
If you really want to use the [row][column] indexing syntax, you can either make a vector-of-vectors (not recommended), or you can index your rows:
vector<int> PixelMapData( (Size.x+1) * (Size.y+1) );
vector<int*> PixelMap( Size.x+1 );
PixelMap[0] = &PixelMapData[0];
for( int i = 0; i < Size.x+1; i++ ) {
PixelMap[i+1] = PixelMap[i] + Size.y + 1;
}
Now you can index in 2D:
int someval = PixelMap[row][col];
There's a couple of problems with your code:
First off:
int PixelMap[Size.x+1][Size.y+1];
for (x=1;x<=Size.x;x++)
for (y=1;y<=Size.y;y++)
PixelMap[x][y]=0;
In the above snipped you are never setting the value of PixelMap[0][0], or PixelMap0, etc. Basically those values will be undefined. Arrays in C++ are 0 indexed so you need to be sure you address those. Also, why are you using Size.x+1 and Size.y+1? Something feels wrong about that.
A better loop would be:
int PixelMap[Size.x][Size.y];
for (x=0;x<Size.x;x++)
for (y=0;y<Size.y;y++)
PixelMap[x][y]=0;
Second, this next bit of code is illegible:
while(PointsCheck<=Points)
{
rands=1+(rand()%10);
RandX=1+(rand()%(Size.x));
RandY=1+(rand()%(Size.y));
if (rands==1 && PointsCheck<=Points && PixelMap[RandX][RandY]==0)
{
PixelMap[RandX][RandY]=CurrentNumber;
CurrentNumber+=2;
PointsCheck++;
}
}
You're only incrementing PointsCheck if
PointsCheck <= Points
Why? You test for this to be true in your while condition. PointsCheck doesn't get incremented anywhere before this test.
rands is never guaranteed to be equal to 1 by the way, so your loop could go on for eternity (though unlikely).
The next loop suffers from similar problems as above:
while(Done==false)
{
Done=true;
What's the reason for this? You never break out of the while loop, and you never set Done to false, so the next block of code will only ever be executed once. remove this bit.
Your for-loops that follow should start at 0 and go while < Size(Size.x and Size.y)
for(x=0;x<Size.x;x++)
for(y=0;y<Size.y;y++)
Fix these issues first, and then if you still have a problem we can move on. And for all our sake, please use brackets {} to scope your for loops and if statements so that we can follow. Also, separate commands onto separate lines. It's a lot of work for us to follow more than one semicolon per line.
EDIT
Since you seem unwilling to fix these issues first:
This could be an issue with the amount of memory allocated on the stack for your program. If you're trying to create an array of 800x800 integers, then you're using 800*800*4 bytes = 2.4 MB of data. I know this is higher than visual studio's default limit of 1 MB, but since a 700x700 array uses 1.8 MB, then whatever program you're using has a higher default (or you set visual studio's higher, but not high enough).
See if you can set your limit to at least 3 MB. More is better, though. If this doesn't fix your scaling problem up to 800, then you have other issues.
EDIT2
I just noticed this:
sf::Vector2i Size;
//unimportant stuff
cin >> Size.x >> Size.y;
int PixelMap[Size.x+1][Size.y+1];
Vector2i will probably have default values for x and y. If you want to dynamically allocate more than what those are, you cannot statically say
PixelMap[Size.x][Size.y]
You need to dynamically allocate the array. I strongly suggest using something like a std::vector > for this
e.g.(untested code):
sf::Vector2i Size;
//unimportant stuff
cin >> Size.x >> Size.y;
std::vector<vector<int> > PixelMap;
//Initialize values to 0
for(size_t i=0; i < Size.x; ++i){
vector<int> nextVec;
for(size_t j=0; j < Size.y; ++j){
nextVec.push_back(0);
}
PixelMap.push_back(nextVec);
}
Not sure if this has anything to do with your crash (I would have added a comment, but I don't have the reputation), but here's a problem I noticed:
Your array indexing scheme is not consistent. Since you're using index 1 to indicate the first element, your bounds checking should look like this...
if (y!=1 && y!=Size.y && x!=1 && x!=Size.x && ...
...instead of this...
if (y!=0 && y!=Size.y && x!=0 && x!=Size.x && ...
[EDIT]
I just tried this:
...
cout << "asdf" << endl;
int PixelMap[Size.x+1][Size.y+1];
cout << "asdf" << endl;
...
and verified it's a stack overflow problem. So, as others mentioned above, allocate your pixel map on the heap and it should be fine.
BTW, this code...
int PixelMap[Size.x+1][Size.y+1];
is not standard C++. It's an extension some compilers provide, called 'variable length arrays'. Check this out for more info -> Why aren't variable-length arrays part of the C++ standard?
[/EDIT]
Related
I have the following code:
/* some calculation */
do {
/* data acquire and calculation */
} while (CONDITION);
My condition looks like one of the following:
(( A || B ) && C )
( A && C )
Note that I use these conditions with different statements for A, B and C. However the pre-calculation and everything inside the loop is always the same. I use this block several times in my code and wondered if there is a possibility to put it in a define or in a function to let the code look cleaner.
Is there a nice and reasonable way to achieve the loop with different statements?
I already thought about a function call in a while loop like
while (DoMyLoop( CONDITION, calculationParams ));
But with this solution I wouldn't have the pre-calculation in my one-liner.
How can I get my code block in a nice one-liner (or more if necessary, as long as it's easy to understand and maintain)?
Some additional (maybe irrelevant) information:
In my loop I receive a byte array and depending on the situation I have to loop until a specific bit changes, therefore the A or B.
C is a timeout condition.
Here is some code with variables
unsigned char data[10] = { 0 };
long intervalMS = 0;
/* precalc */
gettimeofday( &stopTimeout, NULL );
gettimeofday( &startTimeout, NULL );
do {
receiveCall( data );
gettimeofday( &stopTimeout, NULL );
intervalMS = (stopTimeout.tv_sec - startTimeout.tv_sec) * 1000 +
(stopTimeout.tv_usec - startTimeout.tv_usec) / 1000;
} while ( (data[0] & 0x01) && intervalMS < 200);
The A part of the condition can also look like ((data[2] & 0x02) || data[3] == 0x12).
What about next solution?
for (precalculation (); CONDITION; somethingWith (calculationParams));
precalculation () is executed once, the CONDITION is evaluated at every iteration and somethingWith (calculationParams) take the place in of the incrementation. The body of the for loop is empty.
Pure C beauty.
Obviously, precalculation and somethingWith (calculationParams) must become a new function.
First of all, please note that do {} while(something) is equivalent to something=true; while something{}. The former saves a bit of extra execution in case you don't want the initialization part.
How can I get my code block in a nice one-liner
There is nothing wrong with your code. } while ( (data[0] & 0x01) && intervalMS < 200); is perfectly clear to me - another C programmer.
You check if the lsb is set and you check a timer interval. The only way this code could be improved would be to explain why you check the lsb - which you can do with a comment (do you check if a number is odd or do you read a bit in bit-field etc).
Now what you can and should do, is to put the whole snippet inside a function and give it a meaningful name. There's the nice one-liner.
I have some code which I taken from Javascript. Original purpose of the program was to calculate Solar Radiation. It calculates Solar Position, Earth Distance from Sun, Hour Angle, Zenith, Azimuth etc. I tried to analize one part of the program which I have rewritten to C. This is the part where sidereal time is calculated.
Just for context purposes:
// Sidereal time (Theta0)
double GMST = 280.46061837+360.98564736629*( i->JulianDate-2451545.);
// Sidereal_time = GMST + 0.000387933*T2 - T3/38710000
double Sidereal_time = GMST+0.000387933*T*T
-T*T*T/38710000.;
Note: i->JulianDate is Julian Date, which is calculated from user input date.
I have also found some interesting source which describes how to calculate sitereal time here.
The question
Now the part of the code, where I am wondering about it:
// Replacement code for Sidereal=fmod(Sidereal,360.)
double S_save=Sidereal_time/360.;
if (S_save < 0.) Sidereal_time=Sidereal_time-ceil(S_save)*360.;
else Sidereal_time=Sidereal_time-floor(S_save)*360.;
if (Sidereal_time < 0.) Sidereal_time+=360.;
Can you explain to me why this block of condition is there? I see the note: Sidereal=fmod(Sidereal,360.) But I don't see why the author replaced the short code with the long block of conditional statements. Any ideas welcome.
Well, the "replacement" code does something different for negative numbers. This is the proof:
#include <iostream>
#include <cmath>
using namespace std;
double fmod360_alternative(double Sidereal_time) {
double S_save=Sidereal_time/360.;
if (S_save < 0.) Sidereal_time=Sidereal_time-ceil(S_save)*360.;
else Sidereal_time=Sidereal_time-floor(S_save)*360.;
if (Sidereal_time < 0.) Sidereal_time+=360.;
return Sidereal_time;
}
int main() {
double Sidereal_time = -100;
cout << fmod(Sidereal_time,360.0) << endl; // result: -100
cout << fmod360_alternative(Sidereal_time) << endl; // result: 260
return 0;
}
As Bob__ said in the comment section, the "replacement" code keeps the end result in the interval [0.0,360.0). fmod does not.
However, I agree the "replacement" code is more complicated than necessary. But you should keep in mind that not everybody writing code is a programmer and in the space industry (or related) there are a lot of physicists required to write code at some point and they sometimes go for the correctness of the results, rather than performance (which is ok).
I have an array of data in a C++/CLI array that I can pass to a native function using pin_ptr<T>, no problem so far. Now, however, I need to pass the array on to a C++/STL function that expects a container such as std::array or std::vector.
The easy way of doing this (which I did first), is to copy element by element.
The second-easiest way is to call std::copy(), see the answer to this question: convert System::array to std::vector.
However, I want to skip the entire copying step and just use the pointer instead. Seeing as std::array requires a template argument to determine its length, I can't create one at runtime (but please do correct me if I'm wrong). Is there a way to create a vector or a different type of STL container, without unnecessary copying of data?
No it's not possible to do without copying, not with the standard containers anyway.
If you're still okay with copying then you should look at the std::vector constructor because I think the easiest way would be to do e.g.
std::vector<T>(your_pointer, your_pointer + number_of_elements)
If you definitely want to avoid copying, then it's not really that hard to write a simple wrapper around the pointer, including simple iterators needed for iteration (the reason it has to be a standard container I guess).
Just for fun and because I had some time over, I created just such a wrapper. It includes indexing and iterators. No bounds-checking.
See https://gist.github.com/pileon/c21cfba496e6c352dd81
Example program using it:
#include <iostream>
#include "pointer_container.h"
int main()
{
int a[20];
std::iota(a, a + 20, 0); // Initialize array
{
std::cout << "From array : ";
for (const auto item : a)
{
std::cout << item << ' ';
}
std::cout << '\n';
}
pointer_container<int> c(a, 20);
{
std::cout << "From container: ";
for (const auto item : c)
{
std::cout << item << ' ';
}
std::cout << '\n';
}
}
Expected output from the program:
From array : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
From container: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Since C++20 there is a way to use c++ containers with managed arrays in c++/cli that avoids copying the data: std::span
In c++20 it's possible to use std::span to wrap a managed c++/cli array. Then it can be used with standard container algorithms.
Unfortunately, Microsoft doesn't support c++/cli beyond c++17. Consequently one must first pass the pointer and length to a function in a different source file that is compiled using c++latest while compiling the caller's source file using the earlier c++17/cli. Fortunately the ABIs are compatible. This is easily set up for each file in the properties page of Visual Studio 2019.
Here's some sample code that creates a small managed array<double> then calls a function that wraps the managed data with std::span then sorts with std::sort
// file1.cpp compile with /cli
#include <iostream>
using namespace System;
void sortme(double *p, int len);
int main()
{
array<double>^ v = gcnew array<double> {1.0, 3.0, 2.0, 4.0};
pin_ptr<double> pin=&v[0];
int len=v->Length;
sortme(pin, len);
for (int i = 0; i < len; i++)
std::cout << v[i] << "\n"; // prints sorted array
}
// file2.cpp compile with c++latest
#include <span>
#include <algorithm>
void sortme(double *p, int len)
{
std::span data_clr(p, len);
std::sort(data_clr.begin(), data_clr.end());
}
Since std::array is just a wrapper you can cast a regular array to a pointer to a std::array. This isn't usable for other containers of course.
#include <array>
#include <iostream>
void test(std::array<int, 10>* pia)
{
std::cout << (*pia)[0] << std::endl;
}
int main()
{
int ix[10]{ 0 };
test((std::array<int, 10> *) ix);
}
I'm struggling to modify a program that takes two files as input (each representing a vector) and calculates the dot product between them. It's supposed to be done in parallel, but I was told that the number of points in each file might not be evenly divisible by the number of available processors and each process might read from incorrect positions within the files. What I mean is that, if there are four processors, the first 250 points might be correctly read and calculated but the second processor might read over those same 250 points and provide an incorrect result. This is what I've done so far. Any modifications I've made are noted.
#include "fstream"
#include "stdlib.h"
#include "stdio.h"
#include "iostream"
#include "mpi.h"
int main(int argc, char *argv[]){
MPI_Init(&argc, argv);
//parse command line arguments
if( argc < 3 || argc > 3){
std::cout << "*** syntax: " << argv[0] << " vecFile1.txt vecFile2.txt" << std::endl;
return(0);
}
//get input file names
std::string vecFile1(argv[1]);
std::string vecFile2(argv[2]);
//open file streams
std::ifstream vecStream1(vecFile1.c_str());
std::ifstream vecStream2(vecFile2.c_str());
//check that streams opened properly
if(!vecStream1.is_open() || !vecStream2.is_open()){
std::cout << "*** Could not open Files ***" << std::endl;
return(0);
}
//if files are open read their lengths and make sure they are compatible
long vecLength1 = 0; vecStream1 >> vecLength1;
long vecLength2 = 0; vecStream2 >> vecLength2;
if( vecLength1 != vecLength2){
std::cout << "*** Vectors are no the same length ***" << std::endl;
return(0);
}
int numProc; //New variable for managing number of processors
MPI_Comm_size(&numProc,MPI_COMM_WORLD); //Added line to obtain number of processors
int subDomainSize = (vecLength1+numProc-1)/numProc; //Not sure if this is correct calculation; meant to account for divisibility with remainders
//read in the vector components and perform dot product
double dotSum = 0.;
for(long i = 0; i < subDomainSize; i++){ //Original parameter used was vecLength1; subDomainSize used instead for each process
double ind1 = 0.; vecStream1 >> ind1;
double ind2 = 0.; vecStream2 >> ind2;
dotSum += ind1*ind2;
}
std::cout << "VECTOR DOT PRODUCT: " << dotSum << std::endl;
MPI_Finalize();
}
Aside from those changes, I don't know where to go from here. What can I do to make this program properly calculate a dot product of two vectors using paralleling processing with two text files as input? Each contains 100000 points so it's impractical to manually modify the files.
I wont write the code here as it seems to be an assignment problem but I would try to give you some tips to go into right direction.
Each processor has an assigned rank that can be found out using the MPI_Comm_rank API. So for parallel processing you can divide the vectors of the files among the processors such that processor with rank r processes the vectors r*subdomainsize to (r+1)*subdomainsize - 1.
You need to make sure that the vector from correct position is read from the file by a particular processor. Use seek api to go to the right offset and then call the read(>>) operator of your filestream.
For calculating subdomainsize I am not sure whether the equation you mentioned works or not. There can be several approaches. The simplest is to use vectorlength/numProc as subdomainsize. Each processor can handle subdomainsize elements, however the last processor (rank == numProc) will handle the remaining elements.
After the for loop, you should use a reduction operation to collect the individual sums from the processors and sum it up globally for the final result. See MPI_Reduce.
Use Barrier for synchronization between the processors. A barrier must be placed after the for loop and before calling reduction.
I have a project due in my operating systems class where I'm supposed to simulate a translation lookaside buffer.
I'm writing a method that will be called after a TLB-miss. It's supposed to find the next entry in the TLB that is either empty or has not been hit in awhile, delete that entry, and replace it with the entry from the page table that was last called. The data from the page table entry is given when the method is called.
Void tlb_insert(VPAGE_NUMBER new_vpage, PAGEFRAME_NUMBER new_pframe, BOOL new_mbit, BOOL new_rbit)
{
// Starting at the clock_hand'th entry, find first entry to
// evict with either valid bit = 0 or the R bit = 0. If there
// is no such entry, then just evict the entry pointed to by
// the clock hand.
int m;
int evct = clock_hand;
for (m = clock_hand; m < (num_tlb_entries); m++){
if (tlb[m].vbit_and_vpage & VBIT_MASK == 0 || tlb[m].mr_pframe & RBIT_MASK == 0){
evct = m;
break;
}
}
// Then, if the entry to evict has a valid bit = 1,
// write the M and R bits of the of entry back to the M and R
// bitmaps, respectively, in the MMU (see mmu_modify_rbit_bitmap, etc.
// in mmu.h)
if (tlb[evct].vbit_and_vpage & VBIT_MASK == 1){
PAGEFRAME_NUMBER pfr = tlb[evct].mr_pframe & PFRAME_MASK;
int val1 = tlb[evct].mr_pframe & RBIT_MASK;
int val2 = tlb[evct].mr_pframe & MBIT_MASK;
mmu_modify_rbit_bitmap (pfr, val1);
mmu_modify_mbit_bitmap(pfr, val2);
}
// Then, insert the new vpage, pageframe, M bit, and R bit into the
// TLB entry that was just found (and possibly evicted).
tlb[evct].vbit_and_vpage = VBIT_MASK | new_vpage;
tlb[evct].mr_pframe = new_mbit | (new_rbit | new_pframe);
// Finally, set clock_hand to point to the next entry after the
// entry found above.
clock_hand = evct + 1;
}
//Writes the M & R bits in the each valid TLB
//entry back to the M & R MMU bitmaps.
void tlb_write_back()
{
int n;
for (n = 0; n < num_tlb_entries; n++){
if (tlb[n].vbit_and_vpage & VBIT_MASK == 1){
PAGEFRAME_NUMBER pfr = tlb[n].mr_pframe & PFRAME_MASK;
int val1 = tlb[n].mr_pframe & RBIT_MASK;
int val2 = tlb[n].mr_pframe & MBIT_MASK;
mmu_modify_rbit_bitmap (pfr, val1);
mmu_modify_mbit_bitmap(pfr, val2);
}
}
}
I'm getting a segfault from the lines:
tlb[evct].vbit_and_vpage = VBIT_MASK | new_vpage;
tlb[evct].mr_pframe = new_mbit | (new_rbit | new_pframe);
VBIT_MASK is a previously defined variable to mask out the bit I now want to insert. I am not sure if I am misunderstanding how to use bitmasks, or if there is something more seriously wrong with my code. I realize that it would be too much to ask anyone to go through the whole thing in detail, but if anyone had any suggestions for what direction I should be thinking in to fix this, I'd appreciate it!
I draw your attention to how surprisingly low & is in this table:
$ cat /usr/share/misc/operator
Operator Associativity
-------------------------------------------------------------
() [] -> . left to right
! ~ ++ -- - (type) * & sizeof new delete right to left
->* .* left to right
* / % left to right
+ - left to right
<< >> left to right
< <= > >= left to right
== != left to right
& left to right
^ left to right
| left to right
&& left to right
|| left to right
?: right to left
= += -= *= /= %= <<= >>= &= ^= |= throw right to left
?: (C++, third operand) right to left
, left to right
$FreeBSD: src/share/misc/operator,v 1.2.22.1 2009/05/31 18:14:24 ed Exp $
Segfaults are extremely easy to find, assuming the right tools. Normally I just start gdb, look at the backtrace and know the reason at once. So, instead of going through your code (which I don't have), I just give you a general recipe to find any segfault (and many other errors):
If you are using GCC on a Linux system, I recommend you to (re-)compile your code with -Wall -g -ggdb -O0. -Wall will display interesting warnings, which are often the cause for undefined behavior or segfaults, and -g -ggdb adds some useful debugging information to your code and -O0 disables optimization (so that counter variables inside loops aren't optimized out and so on).
After that, you should start the debugger with gdb ./yourprog. Then write run to start your program. After your program has crashed, you will see something like "got segfault, program exited with ...'. Type bt which displays a backtrace (i.e. the stack of function calls including the line numbers and so on.). Just look at the list and search for the first top-most file which is part of your program. With that, you will now know the exact location (file and line number) where the segfault is happening, and normally its extremely easy to decide whats the cause if you know the exact line (just think about what might be unitialized or NULL in that statement).
Alternatively, you can also set a breakpoint yourfile.c:123 at that line (in this example line number 123) and display the content of your variables with print your_var_or_pointer. Examine all variables in that line - now you should finally know whats the cause :D
(PS: I can not give you advice how to debug in other environments such like Visual Studio and so on, but the idea is the same. They all come with an excellent debugger included!)