Error: cannot convert ‘std::vector<double*>’ to ‘double*’

I am trying to convert a malloc to std::vector
This was the original initialization in my code
1
2
3
  double *ne;
  ne = (double*) fftw_malloc(nx*ny*sizeof(double));
  memset(ne, 42, nx*nyk* sizeof(double));

42 here was something large enough that worked for me.
Then, this is what I wrote:
1
2
std::vector<double*> ne(nx*ny); //init in a for loop


I am getting the error:
1
2
3
4
5
 error: cannot convert ‘double’ to ‘__gnu_cxx::__alloc_traits<std::allocator<double*>, double*>::value_type’ {aka ‘double*’} in assignment
  676 |     ne[j + ny*i] = ne0[j + ny*i] + ne1[j + ny*i];
      |                    ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
      |                                  |
      |                                  double

line 676 is an initializing for loop:
1
2
3
4
5
6
7
for (int i = 0; i < nx; i++){
		for (int j = 0; j < ny; j++){
		  ne1[j + ny*i] =  ((rand() % 101)/100. * (Ampl_2 - Ampl_1) + Ampl_1)*n0; 
		
		  ne0[j + ny*i] = (a2 * tanh((XX[j + ny*i] - xgN_left)/ lgN_left) + a * tanh((XX[j + ny*i] - xgN_right)/lgN_right) - a * tanh((XX[j + ny*i] - Lx + xgN_right)/lgN_right) - a2 * tanh((XX[j + ny*i] - Lx + xgN_left)/lgN_left) + d )*n0; 
		  ne[j + ny*i] = ne0[j + ny*i] + ne1[j + ny*i];
..

I got so many errors, I thought I can convert between malloc and std:vector easily and use it for speed.
Just use:

 
std::vector<double> ne(nx * ny, 42);


You don't specify double* (pointer to double), just double.
Last edited on
@seeplus
Thanks for responding. Well, when I do that I get the error:
1
2
3
error: cannot convert ‘std::vector<double>’ to ‘double*’
 initializing argument 1 of ‘void r2cfft(double*, double (*)[2])’
   16 | void r2cfft(double rArr[], double cArr[][ncomp]);

Hello JamieAl,

You define: std::vector<double*> ne(nx*ny) which makes "ne", bad name, a variable to a vector of "double" pointers.

In the line: ne[j + ny*i] = ne0[j + ny*i] + ne1[j + ny*i];. Since "ne" is a vector of "double*"s the rhs of = needs to return an address not a value. So if "ne0" is not an array of "double" pointers. you have a problem.

Andy
1
2
3
4
5
6
7
// double *ne;
// ne = (double*) fftw_malloc(nx*ny*sizeof(double));
// memset(ne, 42, nx*nyk* sizeof(double)); // 42 here was something large enough

// create a vector containing nx*ny double values initialised to something large enough
// DBL_MAX is defined in <cfloat> https://en.cppreference.com/w/cpp/header/cfloat
std::vector<double> ne( nx*ny, DBL_MAX ) ;
Hello JamieAl,

Unfortunately you do not have enough that will compile that can be tested to duplicate the problem.

If you can not post the complete code try cutting it down to enough to duplicate the problem.

Just because the compiler may say the error is in line 676 does not mean that is where it started.

Andy
 
void r2cfft(double*, double (*)[2])


You didn't post this in the OP.

You're going to have to change all the function definitions - and probably also their usage.

I thought I can convert between malloc and std:vector easily and use it for speed.


Yes if malloc is just used for a 1-d array that isn't passed as a function param and if the memory pointer is used as an array. I doubt that using std::vector will give any extra speed.

You don't use memset, memcpy etc with a vector.
Last edited on
Hello @Handy Andy
Sure, I have my full code that I could provide to you. Unfortunately, is HUGE and I guess you'll see why I am trying to change every malloc and fttw_malloc to std::vector.
Here's my code:

https://www.zipshare.com/download/eyJhcmNoaXZlSWQiOiJkMmQ3NTBjMy0yMzk4LTQ5MmMtOThlOC05NzYwOWNmOTRiYzIiLCJlbWFpbCI6ImFzdHJvbHVqeUBnbWFpbC5jb20ifQ==

Last edited on
@seeplus

Yes if malloc is just used for a 1-d array that isn't passed as a function param and if the memory pointer is used as an array. I doubt that using std::vector will give any extra speed.


oh! I see, mm then I probably should go about this some other way.
You don't use memset, memcpy etc with a vector.


you absolutely can. vectors are ensured to be sequential, so if the thing in the vector is a type that can tolerate these, you can use them, eg a vector of bytes. You probably should not do it, but you "can". If you are seeking a faster data copy / move you can write an assembly loop to move the data via the 128 bit register if you have one, copying 16 bytes per operation if supported... remember to check the boundary or pad the space eg if you have 257 bytes there is 1 left over

vectors are plenty fast if used correctly. I had a lot of trouble with them when they first came out, but they have been tweaked and work fine if you understand what things they do that can hurt performance and avoid them as much as possible. There are a few places valarray can do something a vector can't do easily, making those faster in some jobs. Plain arrays, plain pointers, etc can cut a tiny bit of overhead but its an exceptional program where those matter.
Last edited on
> You're going to have to change all the function definitions - and probably also their usage.

Not really; vectors are compatible with C's memory model.
The pointer returned by std::vector<double>::data() (along with the vector's size) can be passed to a C-function. C-code can both read from and write to the elements in the vector.


> If you are seeking a faster data copy / move you can write an assembly loop to move the data
> via the 128 bit register if you have one, copying 16 bytes per operation if supported...

An optimiser should do this automatically for TriviallyCopyable types.
I agree, it should. I ran out of energy trying to run down how the AVX stuff works and whether it has 512 bit registers or not and whether anything makes much use of it yet if it does. It would be really cool if it could shuffle 512 / clock, but I suspect bus bandwidth or something has it locked at 64 in critical areas.
Anyway, some minor testing shows it doing 64 bits at at time as you said. I have been unable to catch anything I have access to in the act of more than this, though.
You don't use memset, memcpy etc with a vector.

you absolutely can.


I didn't say you couldn't. I said you don't. Yes, you can get the data starting memory address using .data() and use this as a memory pointer for memset, memcpy etc. But unless you are really into high-performance and understand memory/cpu organisation etc you normally don't. The member functions (and those from <algorithm> ) are already highly optimised for copying etc.

As I said, if you are currently using malloc() and memory manipulation, you probably won't get any performance improvement using std::vector per se.

Not really; vectors are compatible with C's memory model.
The pointer returned by std::vector<double>::data() (along with the vector's size) can be passed to a C-function. C-code can both read from and write to the elements in the vector.


Yes you can but IMO don't. Pass the vector by ref/const ref and use as a vector - not as a block of memory. Unless there are good reasons, don't mix C++ containers et al with using raw memory.

Last edited on
> Pass the vector by ref/const ref and use as a vector - not as a block of memory.

One can't do that if the function being called is part of a C code base (say, a third-party C library).
@JamieAL, Can you provide some sample input and output?

The ability to execute the code and compare its output would be a major help because it lets us
- use the debugger to test assumptions
- make sure that our transformations don't blow up the program
- use a profiler to guide our optimizations
and so on.
Topic archived. No new replies allowed.