I am trying to use PMPI wrapper to record some function parameters, e.g. MPI_Send's parameter. I need to record them and then I could use them to reconstruct content of all those parameters.
The wrapper for MPI_Send looks like this:
/* ================== C Wrappers for MPI_Send ================== */
_EXTERN_C_ int PMPI_Send(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm);
_EXTERN_C_ int MPI_Send(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm) {
int _wrap_py_return_val = 0;
do_wrap_send_series((char *)"MPI_Send", buf, count, datatype, dest, tag, comm);
_wrap_py_return_val = PMPI_Send(buf, count, datatype, dest, tag, comm);
return _wrap_py_return_val;
}
The problem is that I couldn't record pointer's value and use it later on. Pointer could differ across runs.
At least MPI_Datatype is pointer type, correct me if I am wrong.
How do I find out MPI_Datatype is pointer type: Compile this, mpicc warns (on x86_64):
warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘struct ompi_datatype_t *’
The definition of struct ompi_datatype_t is:
struct ompi_datatype_t {
opal_datatype_t super; /**< Base opal_datatype_t superclass */
/* --- cacheline 5 boundary (320 bytes) was 32 bytes ago --- */
int32_t id; /**< OMPI-layers unique id of the type */
int32_t d_f_to_c_index; /**< Fortran index for this datatype */
struct opal_hash_table_t *d_keyhash; /**< Attribute fields */
void* args; /**< Data description for the user */
void* packed_description; /**< Packed description of the datatype */
uint64_t pml_data; /**< PML-specific information */
/* --- cacheline 6 boundary (384 bytes) --- */
char name[MPI_MAX_OBJECT_NAME];/**< Externally visible name */
/* --- cacheline 7 boundary (448 bytes) --- */
/* size: 448, cachelines: 7, members: 7 */
};
typedef struct ompi_datatype_t ompi_datatype_t;
So it looks like each MPI_Datatype has a unique id.
So I tried to access the id filed with here. I got error:
error: dereferencing pointer to incomplete type ‘struct ompi_datatype_t’
ompi should be internal data structure. Is there any way to achive my goal?
Tool to generate PMPI wrapper: here
Generally speaking, MPI_Datatype is an opaque handler, so you cannot make any assumption, especially if your wrappers should be portable.
MPI_Datatype is indeed a pointer in Open MPI, but it is a number in MPICH iirc.
(older) Fortran uses integer in order to refer a datatype, so one option is to use the following subroutines
MPI_Fint MPI_Type_c2f(MPI_Datatype datatype);
MPI_Datatype MPI_Type_f2c(MPI_Fint datatype);
in order to convert between a MPI_Datatype and a MPI_Fint (an int unless you built Open MPI with 8 bytes Fortran integers)
That being said, if you want to compare datatypes between runs, you might want to consider these subroutines
int MPI_Type_set_name(MPI_Datatype type, const char *type_name);
int MPI_Type_get_name(MPI_Datatype type, char *type_name, int *resultlen);
So you do not have to worry about race conditions nor changing the sequence in which derived datatypes are created by your app.
Related
I have a pointer to some location in memory passed in, void *dataLoc.
Some program is transferring memory there as a bunch of unsigned chars where 0x00 is 0 and 0xFF is one.
I want to be able to pull, say, every 4th char and convert it to the float of what number is supposed to be represented. But I'm having trouble understanding how I get from a void * to an array of char[] to an array of float[].
My initial thought was to do something like
for(i=0,i<100,i++){
floatArray[i] = (float)(*((unsigned char *)dataLoc[4*i])) / 255;
}
the void * is cast to a char *.
the next 4th char is selected from the for loop
the * dereferences the char pointer, which should give me an unsigned char,
the float should change the char into a float, but a float representation of the number I want *255
I divide by 255 to get the fraction I want.
This fails, because I get the error "pointer of type 'void ' used in arithmetic
'void' is not a pointer-to-object type and beyond this, I'm not really confident that the rest of that line will work out the way I would like.
Can someone advise the proper way to handle this?
Good that you had warnings enabled.
dataLoc[4*i] occurs before (unsigned char *)dataLoc and leads to "pointer of type 'void *' used in arithmetic ..."
Cast to unsigned char * first.
Also remove extra level of *. The following is type unsigned char
((unsigned char *)dataLoc)[4*i]
Fixed:
void * dataLoc;
float floatArray[100];
// for(i=0,i<100,i++){ Use ';', not ','
for(int i=0;i<100;i++){
// Cast to `unsigned char *` before using `[]`
// * not needed here ---v
floatArray[i] = (float)( ( ((unsigned char *)dataLoc) [4*i])) / 255;
}
or
for (int i=0; i<100 ;i++) {
unsigned char value = ((unsigned char *)dataLoc)[4*i];
floatArray[i] = value / 255.0f;
}
Using the Arduino Ethernet Server Library, what is the difference between:
server.write(data);,
server.print(data);, and
server.println(data);
I know that the printIn adds a new line, where print does not. I cannot find any examples for server.write();.
(Long answer, skip to TL;DR at the bottom if unwieldy)
Where print() and write() come from
To find out, we can look at the source. Server is an instance of the EthernetServer class defined in arduino/libraries/Ethernet/EthernetServer.h (selected lines only)
#include "Server.h"
class EthernetClient;
class EthernetServer :
public Server {
private:
public:
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);
using Print::write;
};
Ok, so it is a Server. Server is defined in /usr/share/arduino/hardware/arduino/cores/arduino/Server.h, and there is very little to it:
class Server : public Print {
public:
virtual void begin() =0;
};
This means that server is a subclass of Print so we can look for differences between write() and print() there.
print() and write() parameters
We see that this class (i.e. Print) defines a number of overloaded print() methods:
size_t print(const __FlashStringHelper *);
size_t print(const String &);
size_t print(const char[]);
size_t print(char);
size_t print(unsigned char, int = DEC);
size_t print(int, int = DEC);
size_t print(unsigned int, int = DEC);
size_t print(long, int = DEC);
size_t print(unsigned long, int = DEC);
size_t print(double, int = 2);
size_t print(const Printable&);
and three overloaded write() methods:
virtual size_t write(uint8_t) = 0;
size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); }
virtual size_t write(const uint8_t *buffer, size_t size);
As you can see the C-string write uses the block write (the third method), and in the default implementation, the block write uses a byte write (the first method), which is pure virtual method: virtual size_t write(uint8_t) = 0;. It must be overriden in every class that derives from Print. Additionally the block write() may be overriden as well in order to write multi-byte data more efficiently.
So, parameter-wise:
write(): on bytes (uint8_t), byte buffers, and char array pointers (= regular C strings)
print(): Arduino Strings, ints and longs (in whatever base), floats, and any class derived from Printable, in addition to chars and C strings.
As you can see, formally, there is little overlap between the parameters write() and print() takes. For instance only write() takes uint8_t, but only print() can take a char. The only area of overlap is the C-style strings: there is print(const char[]); and write(const char *str);. However, even in cases like char the print() function simply calls the write(uint8_t):
size_t Print::print(char c)
{
return write(c);
}
The same is true for print(char[])
write() in `EthernetServer
The EthernetServer class introduces a block write method
size_t EthernetServer::write(const uint8_t *buffer, size_t size)
and in the EthernetServer the write(uint8_t) simply thunks to the block write:
size_t EthernetServer::write(uint8_t b)
{
return write(&b, 1);
}
Since all the print() calls and non-uint8_t write() calls use either write(uint8_t) or write(uint8_t*, size_t), in the EthernetServer class every print/write call is made using the block write.
Performance and choosing between print() and write()
The thunking print() functions (such as print(char c)) will be most-likely be inlined by the gcc compiler, though if you are worried about this you can call write() instead of print().
One case where you might want to call write() instead of print() to save a couple of clock cycles is where you are holding a byte/uint8_t and you need to print that. Using print() your data will need to be converted to a 4-byte value (int) and then printed using more code. In this case write() will be a tiny bit faster.
On the other hand, code consistency is probably worth something too. From this perspective it might make sense to make all print() calls.
Most of the time, however, your types will dictate calling the print() function: write can only take three types of input.
TL;DR: The answer to your question then is that there isn't much difference between print() and write() except:
The write() methods (byte or block) are the methods that do the actual work of sending characters somewhere, in every case.
write() can take bytes (uint8_t), byte buffers, and char array pointers (= regular C strings) as parameters, whereas print() takes Arduino Strings, ints and longs (in whatever base), floats, and any class derived from Printable, in addition to chars and C strings. So we might say that write() is lower level than print(), given the fact that it only takes low-level types.
Most of the time your output types will dictate which one to use. To make the fastest code use write() for printing byte/uint8_t types, but print everywhere makes your code look a teensy bit better IMHO (mainly because it doesn't raise the print() versus write() questions).
I have the following struct:
typedef union
{
struct
{
unsigned char ID;
unsigned short Vdd;
unsigned char B1State;
unsigned short B1FloatV;
unsigned short B1ChargeV;
unsigned short B1Current;
unsigned short B1TempC;
unsigned short B1StateTimer;
unsigned short B1DutyMod;
unsigned char B2State;
unsigned short B2FloatV;
unsigned short B2ChargeV;
unsigned short B2Current;
unsigned short B2TempC;
unsigned short B2StateTimer;
unsigned short B2DutyMod;
} bat_values;
unsigned char buf[64];
} BATTERY_CHARGE_STATUS;
and I am stuffing it from an array as follows:
for(unsigned char ii = 0; ii < 64; ii++) usb_debug_data.buf[ii]=inBuffer[ii];
I can see that the array has the following (arbitrary) values:
inBuffer[0] = 80;
inBuffer[1] = 128;
inBuffer[2] = 12;
inBuffer[3] = 0;
inBuffer[4] = 23;
...
now I want display these values by changing the text of a QEditLine:
str=QString::number((int)usb_debug_data.bat_values.ID);
ui->batID->setText(str);
str=QString::number((int)usb_debug_data.bat_values.Vdd)
ui->Vdd->setText(str);
str=QString::number((int)usb_debug_data.bat_values.B1State)
ui->B1State->setText(str);
...
however, the QEditLine text values are not turning up as expected. I see the following:
usb_debug_data.bat_values.ID = 80 (correct)
usb_debug_data.bat_values.Vdd = 12 (incorrect)
usb_debug_data.bat_values.B1State = 23 (incorrect)
seems like 'usb_debug_data.bat_values.Vdd', which is a short, is not taking its value from inBuffer[1] and inBuffer[2]. Likewise, 'usb_debug_data.bat_values.B1State' should get its value from inBuffer[3] but for some reason is picking up its value from inBuffer[4].
Any idea why this is happening?
C and C++ are free to insert padding between elements of a structure, and beyond the last element, for whatever purposes it desires (usually efficiency but sometimes because the underlying architecture does not allow unaligned access at all).
So you'll probably find that items of two-bytes length are aligned to two-byte boundaries, so you'll end up with something like:
unsigned char ID; // 1 byte
// 1 byte filler, aligns following short
unsigned short Vdd; // 2 bytes
unsigned char B1State; // 1 byte
// 3 bytes filler, aligns following int
unsigned int myVar; // 4 bytes
Many compilers will allow you to specific how to pack structures, such as with:
#pragma pack(1)
or the gcc:
__attribute__((packed))
attribute.
If you don't want to (or can't) pack your structures, you can revert to field-by-filed copying (probably best in a function):
void copyData (BATTERY_CHARGE_STATUS *bsc, unsigned char *debugData) {
memcpy (&(bsc->ID), debugData, sizeof (bsc->ID));
debugData += sizeof (bsc->ID);
memcpy (&(bsc->Vdd), debugData, sizeof (bsc->Vdd));
debugData += sizeof (bsc->Vdd);
: : :
memcpy (&(bsc->B2DutyMod), debugData, sizeof (bsc->B2DutyMod));
debugData += sizeof (bsc->B2DutyMod); // Not really needed
}
It's a pain that you have to keep the structure and function synchronised but hopefully it won't be changing that much.
Structs are not packed by default so the compiler is free to insert padding between members. The most common reason is to ensure some machine dependent alignment. The wikipedia entry on data structure alignment is a pretty good place to start. You essentially have two choices:
insert compiler specific pragmas to force alignment (e.g, #pragma packed or __attribute__((packed))__.
write explicit serialization and deserialization functions to transform your structures into and from byte arrays
I usually prefer the latter since it doesn't make my code ugly with little compiler specific adornments everywhere.
The next thing that you are likely to discover is that the byte order for multi-byte integers is also platform specific. Look up endianness for more details
I have to transfer a number of elements of type:
typedef struct
{
float w;
int a, b;
} edge;
to different processes, hence I am creating an MPI derived type like this:
unsigned int typecount;
MPI_Datatype PEDGE, types[2] = { MPI_FLOAT, MPI_INT };
MPI_Aint offsets[2], extent;
int blocklen[2] = { 1, 2 };
typecount = 2;
offsets[0] = 0;
MPI_Type_extent(MPI_FLOAT, &extent);
offsets[1] = (1*extent);
MPI_Type_struct (typecount, blocklen, offsets, types, &PEDGE);
MPI_Type_commit(&PEDGE);
When I do a sizeof(edge) I get 12 bytes, but I am getting only 8 bytes when I do sizeof(PEDGE)...why is that? Apart from this, my code for sending some elements of PEDGE type to arrays of edge type are failing, probably because of this mismatch.
The problem here is that an MPI_Datatype object such as PEDGE is not itself the new datatype, merely an opaque handle to some implementation-specific entity that MPI can interpret as a datatype. As such, sizeof() will not be able to return its accurate size. Use MPI_Type_size() instead.
As for the sends failing, I can't say much without seeing your code, but your datatype definition does look correct.
people, i've an issue now..
#include <stdio.h>
#include <stdlib.h>
typedef struct a
{
int *aa;
int *bb;
struct b *wakata;
}a;
typedef struct b
{
int *you;
int *me;
}b;
int main()
{
a *aq;
aq = (a*)malloc(sizeof(a*));
*aq->wakata->you = 1;
*aq->wakata->me = 2;
free(aq);
return 0;
}
and compiled, then debugged :
gcc -o tes tes.c --debug
sapajabole#cintajangankaupergi:/tmp$ gdb -q ./tes
Reading symbols from /tmp/tes...done.
(gdb) r
Starting program: /tmp/tes
Program received signal SIGSEGV, Segmentation fault.
0x08048414 in main () at tes.c:22
22 *aq->wakata->you = 1;
well, the question is, how to set the value to variable inside struct 'b' through struct 'a' ?
anyone ?
The initial allocation of a is only allocating 4 bytes (in a 32-bit architecture). It should be:
aq = (a*)malloc(sizeof(a));
And wakata has not been initialized: Maybe this:
aq->wakata = (b*)malloc(sizeof(b));
And it will need a corresponding free as well prior to the free of aq.
free(aq->wakata);
And since you have pointers to the integers, those would also need to be allocated (you and me). But it is not clear if that is your goal. You probably should remove the * from the int declarations so that they are simply int members rather than the pointers to int.
Looks like you have a few mistakes here. See the code below.
In general a few things to keep in mind. You can't access memory before you malloc it. Also, there is a difference between memory and pointers e.g. int and int *
#include <stdio.h>
#include <stdlib.h>
typedef struct a
{
int aa;
int bb;
struct b *wakata;
}a;
typedef struct b
{
int you;
int me;
}b;
int main()
{
a * aq = malloc(sizeof(a));
aq->wakata = malloc(sizeof(b))
aq->wakata->you = 1;
aq->wakata->me = 2;
free(aq->wakata)
free(aq);
return 0;
}
wakata isn't pointing to any valid memory. You have to malloc memory for it, and then also for wakata->you and wakata->me
Pointers do not contain data. They point at data. That is why they are called pointers.
When you malloc enough space to store an a instance named aq, you allocate space for the pointers contained in that structure. You do not cause them to point at anything, nor do you allocate space to contain the things that they would point at.
You're not allocating space for b in struct a. You have defined 'a' as holding pointers, not structs. Also, I think malloc(sizeof(a*)) should be malloc(sizeof(a))
aq = (a*)malloc(sizeof(a)); // You should probably use calloc here
aq->wakata = (b*)malloc(sizeof(b));
you and me don't seem to need to be pointers, just normal ints
You have some problems with your code.
When you allocate memory for the struct a, you should do
aq = (a*)malloc(sizeof(a));
You now allocated memory for the struct a, but not for the struct b pointed by the wakata member, so you need to do
aq->wakata = (b*)malloc(sizeof(b));
Finally, in the struct b there should not be int* members, but int members. This way, you'll be able to correctly assign a value to them.
Remember that you should check for the correct allocation of memory by checking if the malloc return value is not NULL.