@@ -589,6 +589,8 @@ void MpiWorld::send(int sendRank,
589
589
MpiMessageType messageType)
590
590
{
591
591
// Sanity-check input parameters
592
+ // TODO: should we just make this assertions and wait for something else
593
+ // to seg-fault down the line?
592
594
checkRanksRange (sendRank, recvRank);
593
595
if (getHostForRank (sendRank) != thisHost) {
594
596
SPDLOG_ERROR (" Trying to send message from a non-local rank: {}" ,
@@ -609,34 +611,45 @@ void MpiWorld::send(int sendRank,
609
611
.recvRank = recvRank,
610
612
.typeSize = dataType->size ,
611
613
.count = count,
612
- .messageType = messageType,
613
- .buffer = nullptr };
614
+ .messageType = messageType };
614
615
615
616
// Mock the message sending in tests
617
+ // TODO: can we get rid of this atomic in the hot path?
616
618
if (faabric::util::isMockMode ()) {
617
619
mpiMockedMessages[sendRank].push_back (msg);
618
620
return ;
619
621
}
620
622
621
- bool mustSendData = count > 0 && buffer != nullptr ;
623
+ size_t dataSize = count * dataType->size ;
624
+ bool mustSendData = dataSize > 0 && buffer != nullptr ;
622
625
623
626
// Dispatch the message locally or globally
624
627
if (isLocal) {
625
628
// Take control over the buffer data if we are gonna move it to
626
629
// the in-memory queues for local messaging
627
630
if (mustSendData) {
628
- void * bufferPtr = faabric::util::malloc (count * dataType->size );
629
- std::memcpy (bufferPtr, buffer, count * dataType->size );
631
+ if (dataSize < MPI_MAX_INLINE_SEND) {
632
+ std::memcpy (msg.inlineMsg , buffer, count * dataType->size );
633
+ } else {
634
+ void * bufferPtr = faabric::util::malloc (count * dataType->size );
635
+ std::memcpy (bufferPtr, buffer, count * dataType->size );
630
636
631
- msg.buffer = bufferPtr;
637
+ msg.buffer = bufferPtr;
638
+ }
639
+ } else {
640
+ msg.buffer = nullptr ;
632
641
}
633
642
634
643
SPDLOG_TRACE (
635
644
" MPI - send {} -> {} ({})" , sendRank, recvRank, messageType);
636
645
getLocalQueue (sendRank, recvRank)->enqueue (msg);
637
646
} else {
638
647
if (mustSendData) {
639
- msg.buffer = (void *)buffer;
648
+ if (dataSize < MPI_MAX_INLINE_SEND) {
649
+ std::memcpy (msg.inlineMsg , buffer, count * dataType->size );
650
+ } else {
651
+ msg.buffer = (void *)buffer;
652
+ }
640
653
}
641
654
642
655
SPDLOG_TRACE (
@@ -704,17 +717,25 @@ void MpiWorld::doRecv(const MpiMessage& m,
704
717
}
705
718
assert (m.messageType == messageType);
706
719
assert (m.count <= count);
720
+ size_t dataSize = m.count * dataType->size ;
707
721
708
722
// We must copy the data into the application-provided buffer
709
- if (m. count > 0 && m. buffer != nullptr ) {
723
+ if (dataSize > 0 ) {
710
724
// Make sure we do not overflow the recepient buffer
711
725
auto bytesToCopy =
712
726
std::min<size_t >(m.count * dataType->size , count * dataType->size );
713
- std::memcpy (buffer, m.buffer , bytesToCopy);
714
727
715
- // This buffer has been malloc-ed either as part of a local `send`
716
- // or as part of a remote `parseMpiMsg`
717
- faabric::util::free ((void *)m.buffer );
728
+ if (dataSize > MPI_MAX_INLINE_SEND) {
729
+ assert (m.buffer != nullptr );
730
+
731
+ std::memcpy (buffer, m.buffer , bytesToCopy);
732
+
733
+ // This buffer has been malloc-ed either as part of a local `send`
734
+ // or as part of a remote `parseMpiMsg`
735
+ faabric::util::free ((void *)m.buffer );
736
+ } else {
737
+ std::memcpy (buffer, m.inlineMsg , bytesToCopy);
738
+ }
718
739
}
719
740
720
741
// Set status values if required
@@ -1886,21 +1907,34 @@ MpiMessage MpiWorld::recvBatchReturnLast(int sendRank,
1886
1907
// Copy the request id so that it is not overwritten
1887
1908
int tmpRequestId = itr->requestId ;
1888
1909
1889
- // Copy into current slot in the list, but keep a copy to the
1890
- // app-provided buffer to read data into
1910
+ // Copy the app-provided buffer to recv data into so that it is
1911
+ // not overwritten too. Note that, irrespective of wether the
1912
+ // message is inlined or not, we always use the buffer pointer to
1913
+ // point to the app-provided recv-buffer
1891
1914
void * providedBuffer = itr->buffer ;
1915
+
1916
+ // Copy into current slot in the list
1892
1917
*itr = getLocalQueue (sendRank, recvRank)->dequeue ();
1893
1918
itr->requestId = tmpRequestId;
1894
1919
1895
- if (itr->buffer != nullptr ) {
1920
+ // If we have send a non-inlined message, copy the data into the
1921
+ // provided buffer, free the one in the queue,
1922
+ size_t dataSize = itr->count * itr->typeSize ;
1923
+ if (dataSize > MPI_MAX_INLINE_SEND) {
1924
+ assert (itr->buffer != nullptr );
1896
1925
assert (providedBuffer != nullptr );
1897
- // If buffers are not null, we must have a non-zero size
1898
- assert ((itr->count * itr->typeSize ) > 0 );
1899
1926
std::memcpy (
1900
1927
providedBuffer, itr->buffer , itr->count * itr->typeSize );
1928
+
1901
1929
faabric::util::free (itr->buffer );
1930
+
1931
+ itr->buffer = providedBuffer;
1932
+ } else if (dataSize > 0 ) {
1933
+ std::memcpy (
1934
+ providedBuffer, itr->inlineMsg , itr->count * itr->typeSize );
1935
+ } else {
1936
+ itr->buffer = providedBuffer;
1902
1937
}
1903
- itr->buffer = providedBuffer;
1904
1938
}
1905
1939
assert (itr->messageType != MpiMessageType::UNACKED_MPI_MESSAGE);
1906
1940
0 commit comments