I am currently working on a big project involving repast_hpc and mpi. I wanted to implement a two dimensional shared (across processes) array, because repast_hpc itself does not seem to come with that. For that I need an array member of a class. However I do not know the size of the array at compile time.
I need to be able to access and change the values in constant time. The code given below is my current header file, where the problem is located. How can I get a array member like the values in array in c++11?
template <typename Value>
class SharedValueField {
private:
Value[][] values;
std::queue<ValueChangePackage<Value>> changes;
public:
void initializeValueChange(int x, int y, Value value);
Value getValue(int x, int y);
void update();
};
All help appreciated. Thanks!
Tritos
I already tried using std::array. That has the same problems. I cant use std::vector, because they dont allow for constnt-time random element value manipulation.
Using ‚std::vector‘ works after all. As explained by many people in the comments, only changing the size of the vector has time-complexity in O(n). I only need to reassign elements, which works fine.
Related
I am working on quite a big parallel application using OpenMPI to distribute data among MPI Processses. Using MPI with some serialization library, such as "cereal" makes it very comfortable to pass huge-multi embedded objects around. To give a hint of what I mean by multi-embedded structure, I am currently working with simplified version, such as :
// structures for CUDA - this is inside std::vector<struct_multi_data> multi_data_vector
struct struct_multi_data{
int intended_kernel_block;
int intended_kernel_thread;
std::vector<float> data_float;
std::vector<float> data_int;
float result;
};
struct struct_unique_data{
// this structure is shared among all blocks/threads
float x;
float y;
float z;
};
class Data_object{
// functions
public:
Data_object();
~Data_object();
int resize(int multi_data_vector_len, int data_float_len, int data_int_len);
void set_id(int id);
int clean(void);
int get_multi_data_len();
int get_multi_data(struct_multi_data * data, int vector_element);
int set_multi_data(struct_multi_data * data, int vector_element);
// variables
private:
std::vector<struct_multi_data> multi_data_vector;
struct_unique_data unique_data;
int data_id;
};
* the above code is simplified, I have removed serialization functions and some other basic stuff, but the overall structure holds
To put it simply, I am moving around the Data_object, containing vector{struct_multi_data}, which is a vector of structures, where every structure struct_multi_data contains some vector{float}.
I have a good reason to embed all the data into 1 Data_object, as it simplifies the MPI sending and receiving.
QUESTION
Is there some comfortable way to move the Data_object to GPU memory using cudaMalloc/cudaMemcpy functions ?
There seems to be problem with regular std::vector. I dont want to rely on Thrust library, because I am not sure whether it would work with my MPI serialization solution.
EDIT QUESTION
Can I use managed for my Data_object, or cudaMallocManaged() to make the data accessible to GPU ?
PLEASE READ
The size of the Data_object is well defined at the beginning of the program execution. None of the vectors changes size anywhere else, but the beginning of the execution. So why am I using vectors ? this way I can set the vectors size by passing parameters, instead of re-compiling the program to change the data size (such as when the data are defined as arrays).
RESPONSE TO COMMENTS
1) I think can replace all the vectors with pointers to arrays.
No, and the extra sections in this question don't help. std::vector is just not intended to work that way: It "owns" the memory it points to, and if you mem-copy it someplace else (even in host memory) and use it from there, you'll just corrupt your memory. Also, the std::vector code can't even run on the GPU since it's not __device__-code.
What you could do is use an std::span, which doesn't own the memory, instead of the std::vector. If you do that, and the memory is managed, then mem-copying a class might work.
Note I'm completely disregarding the members other than the vector as that seems to be the main issue here.
I am using dlib library for non-linear opitmization. I have looked examples and wrote my program as in example. Everything works fine. Here is code example:
const int N = 9;
typedef matrix<double,N,1> parameter_vector;
parameter_vector residual_derivative{
.....
}
Now, I want to be able to dynamically change number of parameters to be optimized. How should I do it? I know that it is not possible to dynamically create typedef. I want to do something like this(it is not compiling)
class A{
public:
OptimizationWrapper(int N):N(N){
typedef matrix<double,N,1> parameter_vector;
}
int N;
parameter_vector residual_derivative{
.....
}
};
I found only one solution. It is to make 'parameter_vector' size to be lesser then max number of optimize parameters:
typedef matrix<double,100,1> parameter_vector;
int N; //real number of parameters
However this method slows program. Is there another solution?
You cannot specify the size at runtime and still use the compile-time construct of using N to instantiate a template. If you wish to do it at compile time you can make a template function or class:
template<int N> matrix<double,N,1> residual_derivative(...) {...}
The only way to do this at runtime is to use a type which is resized at runtime. I don't know which matrix template you're using, but since it seems to be one-dimensional, perhaps you could return a std::vector<double> instead.
The matrix has constructors that let you set the size at runtime. Call one of those to do it. Here are a bunch of examples:
matrix<double> mat(4,5);
matrix<double,0,1> column_vect(6);
TL;DR: Help me pass vector array input into a function that originally took in int pointers and ints.
I am in a college class that is learning about well-known algorithms. In this class, we use C++ to code the given algorithms. There was no pre-req class to learn C++, so my knowledge is pretty low when it comes to some of the major stuff with programming.
My problem: I have to create a program that takes an input file, sorts it with the user's choice of sorting algorithm, and write the results to an output file. My original code that works perfectly uses an input file of 20 items, placed into an array of length 20, and sorts no problem with each individual sorting algorithm.
Since last night, the only thing I have changed is that my input goes to a vector array, since the teacher will give us files of varying length (10 items to 1,000,000 items). I have four sorting algorithms that need to sort these given input files. Only one of them works, and it does not pass any variables into the function.
The other 3 originally passed in array pointers and other variables, however they do not work with my new input now going to a vector array instead of an int array. I know that what I am passing in needs to be changed, but I have no idea how to do this correctly. I have tried many different ways from sources found on the internet (with pointers and references), but I have had no luck. Here is some snipets of the code I'm using.
vector<int> A;
void insertionSort() // This works no problem as is.
void split(int* A, int* B, int low, int high) //code for Merge-Sort
{
//recurisvely calls split() and splitMerge()
}
void splitMerge(int* A, int* B, int low, int mid, int high) // more code for Merge-Sort
{
// more code for Merge-Sort
}
//quickSort() and countSort() also pass ints and do not work either.
//small part of main()
for (i = 0; unsorted >> temp; i++)
{
A.push_back(temp);
cout << A[i] << "\n";
length++; //I use int length extensively in for-loops in my functions
}
Last thing. I do not get an error when trying to run the Merge-Sort. It just freezes my console window.
conversion from vector to array is done this way
vector vInts;
...fill the vector
int * intArr=vInts[0]
so you don't need to modify your code too much
I believe there is not enough code to make an accurate prediction on where the error may be, but I think the problem is that the sorting algorithms is doing something like A++ with you pointers to access the next member.
Because arrays store the pointer to the next array inside the object and not on adjacent cells of memory, your algorithms are cycling through stuff they shouldn't.
If this is the case, the solution to your problem is to use an iterator instead of a pointer.
void split(A.begin(), B.begin(), int low, int high)
I have to create a three-dimensional array using class A as element ,class A is defined like below, should I use vector<vector<vector<A> > > or boost::multi_array? Which one is better?
struct C
{
int C_1;
short C_2;
};
class B
{
public:
bool B_1;
vector<C> C_;
};
class A
{
public:
bool A_1;
B B_[6];
};
If you know the size of all three dimensions at the time, that you write your code, and if you don't need checking for array bounds, then just use traditional arrays:
const int N1 = ...
const int N2 = ...
const int N3 = ...
A a[N1][N2][N3]
If the array dimensions can onlybe determined at run time, but remain constant after program initialization, and if array usage is distributed uniformly, then boost::multi_array is your friend. However, if a lot of dynamic extension is going on at runtime, and/or if array sizes are not uniform (for example, you need A[0][0][0...99] but only A[2][3][0...3]), then the nested vector is likely the best solution. In the case of non-uniform sizes, put the dimension, whose size variies the most, as last dimension. Also, in the nested vector solution, it is generally a good idea to put small dimensions first.
The main concern that I would have about using vector<vector<vector<A> > > would be making sure that the second- and third-level vectors all have the same length like they would in a traditional 3D array, since there would be nothing in the data type to enforce that. I'm not terribly familiar with boost::multi_array, but it looks like this isn't an issue there - you can resize() the whole array, but unless I'm mistaken you can't accidentally remove an item from the third row and leave it a different size than all of the other rows (for example).
So assuming concerns like file size and compile time aren't much of an issue, I would think you'd want boost::multi_array. If those things are an issue, you might want to consider using a plain-old 3D array, since that should beat either of the other two options hands-down in those areas.
I have been reading up on C++ lately, especially STL, and I decided to do the Knights Tour problem again. I'm thinking about the best way to implement this, and I'm looking for some help.
Just for fun and practice, I thought I'd start with a "Piece" base class, which a "Knight" class can inherit from. I want to do this so I later can try adding other pieces(even though most of the pieces can't walk over the whole board and complete the problem).
So the "piece class" will need some sort of container to store the coordinates of the piece on the board and the number of moves it has made in that specific step.
I'm thinking I need a linked list with 64 (8 * 8) places to do this most efficiently, containing x,y and moves.
Looking at the STL containers, I can't find anything except map that will hold more than one type.
What can I do to store the coordinate pair and an int for the number of moves in one container? Are there more efficient ways of doing this than using vector, list or map? Do I need a custom container?
Thanks!
You can use
struct CellInfo
{
int x, y, move_count;
}
And store it in std::vector for constant access.
Apart from STL and encapsulation, a very efficient way is to use arrays:
pair<int, int> piece_pos[N];
int piece_move[N];
This avoids the overhead of memory leakage and is faster than dynamic allocation.
If you stell want to use STL, then:
vector<pair<int, int> > piece_pos(N);
vector<int> piece(N);
The C++ STL now has static arrays as well. If you want to store the number of times a given x,y coordinate has been moved to, you can create an array of arrays like the following:
using container_type = std::array<std::array<int, 8>, 8>;
// ...
container_type c;
int moves = c[x][y]; // constant-time access.
If you don't need to look moves up based on x,y, and just want the data stored efficiently, use a flat array of size 8x8 = 64.
If your compiler is out of date, consider using std::vector instead.