/// <summary> /// Determine the number of elements transmitted by the communication /// operation associated with this object. /// </summary> /// <param name="type"> /// The type of data that will be stored in the message. /// </param> /// <returns> /// If the type of the data is a value type, returns the number /// of elements in the message. Otherwise, returns <c>null</c>, /// because the number of elements stored in the message won't /// be known until the message is received. /// </returns> public int?Count(Type type) { MPI_Datatype datatype = DatatypeCache.GetDatatype(type); if (datatype != Unsafe.MPI_DATATYPE_NULL) { int count; unsafe { int errorCode = Unsafe.MPI_Get_count(ref status, datatype, out count); if (errorCode != Unsafe.MPI_SUCCESS) { throw Environment.TranslateErrorIntoException(errorCode); } } return(count); } return(null); }
public static unsafe extern int MPI_Type_contiguous(int count, MPI_Datatype oldtype, out MPI_Datatype newtype);
public static unsafe extern int MPI_Scatterv(IntPtr sendbuf, int[] sendcounts, int[] displs, MPI_Datatype sendtype, IntPtr recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm);
public static unsafe extern int MPI_Send(IntPtr buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm);
public static unsafe extern int MPI_Type_free(ref MPI_Datatype datatype);
public static unsafe extern int MPI_Type_size(MPI_Datatype datatype, out int size);
public static unsafe extern int MPI_Pack_size(int incount, MPI_Datatype datatype, MPI_Comm comm, out int size);
public static unsafe extern int MPI_Type_struct(int count, int[] array_of_blocklengths, MPI_Aint[] array_of_displacements, MPI_Datatype[] array_of_types, out MPI_Datatype newtype);
public static unsafe extern int MPI_Alltoall(IntPtr sendbuf, int sendcount, MPI_Datatype sendtype, IntPtr recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm);
public static unsafe extern int MPI_Allgatherv(IntPtr sendbuf, int sendcount, MPI_Datatype sendtype, IntPtr recvbuf, int[] recvcounts, int[] displs, MPI_Datatype recvtype, MPI_Comm comm);
public static unsafe extern int MPI_Irecv(IntPtr buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, out MPI_Request request);
public static unsafe extern int MPI_Isend(IntPtr buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, out MPI_Request request);
public static unsafe extern int MPI_Get_count(ref MPI_Status status, MPI_Datatype datatype, out int count);
public static unsafe extern int MPI_Sendrecv(IntPtr sendbuf, int sendcount, MPI_Datatype senddatatype, int dest, int sendtag, IntPtr recvbuf, int recvcount, MPI_Datatype recvdatatype, int source, int recvtag, MPI_Comm comm, out MPI_Status status);
public static unsafe extern int MPI_Recv(IntPtr buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, out MPI_Status status);
public static unsafe extern int MPI_Type_hvector(int count, int blocklength, MPI_Aint stride, MPI_Datatype oldtype, out MPI_Datatype newtype);
public static unsafe extern int MPI_Type_hindexed(int count, int[] array_of_blocklengths, MPI_Aint[] array_of_displacements, MPI_Datatype oldtype, out MPI_Datatype newtype);
public static unsafe extern int MPI_Alltoallw(IntPtr sendbuf, int[] sendcnts, int[] sdispls, MPI_Datatype[] sendtypes, IntPtr recvbuf, int[] recvcnts, int[] rdispls, MPI_Datatype[] recvtypes, MPI_Comm comm);
public static unsafe extern int MPI_Unpack(IntPtr inbuf, int insize, ref int position, IntPtr outbuf, int outcount, MPI_Datatype datatype, MPI_Comm comm);
public static unsafe extern int MPI_Bcast(IntPtr buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm);
public static unsafe extern int MPI_Type_extent(MPI_Datatype datatype, out MPI_Aint extent);
public static unsafe extern int MPI_Gather(IntPtr sendbuf, int sendcount, MPI_Datatype sendtype, IntPtr recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm);
public static unsafe extern int MPI_Type_commit(ref MPI_Datatype datatype);
public static unsafe extern int MPI_Reduce_scatter(IntPtr sendbuf, IntPtr recvbuf, int[] recvcounts, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm);
public static unsafe extern int MPI_Scan(IntPtr sendbuf, IntPtr recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm);
/// <summary> /// Builds a new MPI datatype by using reflection on the given type. /// </summary> private static MPI_Datatype BuildDatatype(Type type) { // Try to build an MPI datatype using reflection, and return that value. FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); int[] blocklens = new int[fields.Length]; MPI_Aint[] indices = new MPI_Aint[fields.Length]; MPI_Datatype[] types = new MPI_Datatype[fields.Length]; int actualLength = 0; // Walk the fields of the data structure, computing offsets and types // for the MPI datatype foreach (FieldInfo field in fields) { // Only include non-static, serialized fields if (!field.IsStatic && !field.IsNotSerialized) { Type fieldType = field.FieldType; // The type stored in the field int fieldLength = 1; // Number of elements in this field. > 1 only for "fixed" fields // Handle "fixed" arrays in structures, such as: // // struct Dimensions // { // public unsafe fixed float values[11]; // } // // .NET 2.0 uses a synthesized type whose name contains "__FixedBuffer" for this // field. The type itself has size = sizeof(float)*11, and contains a field // named "FixedElementType", whose type is "float". if (fieldType.Name.Contains("__FixedBuffer")) { // Dig out the inner field FieldInfo innerField = fieldType.GetFields()[0]; // Determine the number of elements fieldLength = Marshal.SizeOf(fieldType) / Marshal.SizeOf(innerField.FieldType); // Pull out the type of the fixed array fieldType = innerField.FieldType; } // Find the field's MPI datatype MPI_Datatype fieldDatatype = GetDatatype(fieldType); if (fieldDatatype == Unsafe.MPI_DATATYPE_NULL) { // There is no MPI datatype for this field, so we cannot build a // datatype for this struct. Note this failure and return. return(Unsafe.MPI_DATATYPE_NULL); } // Compute the offset of this field int fieldOffset = (int)Marshal.OffsetOf(type, field.Name); // Record this field blocklens[actualLength] = fieldLength; indices[actualLength] = new IntPtr(fieldOffset); types[actualLength] = fieldDatatype; ++actualLength; } } // Create the MPI datatype MPI_Datatype datatype; unsafe { // Build the MPI datatype as a "structure" int errorCode = Unsafe.MPI_Type_struct(actualLength, blocklens, indices, types, out datatype); if (errorCode != Unsafe.MPI_SUCCESS) { throw Environment.TranslateErrorIntoException(errorCode); } // Commit the newly-constructed MPI datatype errorCode = Unsafe.MPI_Type_commit(ref datatype); if (errorCode != Unsafe.MPI_SUCCESS) { throw Environment.TranslateErrorIntoException(errorCode); } } return(datatype); }