Split ihipCtx_t into ihipCtx_t and ihipDevice_t .

Major change to existing code base.
    Ctx holds streams, enables peers, and flags.
    Device holds accelerator, hsa-agent, device props.

Add hipCtx_t.

Add peer APIs that accept hipCtx_t (in addition to deviceId)

Compiles and passes directed tests.

Change-Id: Iddab1eb9edbf90caad2ef5959c6b811d658197f1
This commit is contained in:
Ben Sander
2016-08-08 11:55:57 -05:00
والد 6aeb2dc8d6
کامیت cfdacab32f
7فایلهای تغییر یافته به همراه687 افزوده شده و 531 حذف شده
+78 -33
مشاهده پرونده
@@ -23,25 +23,32 @@ THE SOFTWARE.
#include "hcc_detail/hip_hcc.h"
#include "hcc_detail/trace_helper.h"
// Peer access functions.
// There are two flavors:
// - one where contexts are specified with hipCtx_t type.
// - one where contexts are specified with integer deviceIds, that are mapped to the primary context for that device.
// The implementation contains a set of internal ihip* functions which operate on contexts. Then the
// public APIs are thin wrappers which call into this internal implementations.
// TODO - actually not yet - currently the integer deviceId flavors just call the context APIs. need to fix.
/**
* HCC returns 0 in *canAccessPeer ; Need to update this function when RT supports P2P
*/
//---
hipError_t hipDeviceCanAccessPeer (int* canAccessPeer, int deviceId, int peerDeviceId)
hipError_t hipDeviceCanAccessPeer (int* canAccessPeer, hipCtx_t *thisCtx, hipCtx_t *peerCtx)
{
HIP_INIT_API(canAccessPeer, deviceId, peerDeviceId);
HIP_INIT_API(canAccessPeer, thisCtx, peerCtx);
hipError_t err = hipSuccess;
auto thisDevice = ihipGetDevice(deviceId);
auto peerDevice = ihipGetDevice(peerDeviceId);
if ((thisDevice != NULL) && (peerDevice != NULL)) {
if (deviceId == peerDeviceId) {
if ((thisCtx != NULL) && (peerCtx != NULL)) {
if (thisCtx == peerCtx) {
*canAccessPeer = 0;
} else {
#if USE_PEER_TO_PEER>=2
*canAccessPeer = peerDevice->_acc.get_is_peer(thisDevice->_acc);
*canAccessPeer = peerCtx->getDevice()->_acc.get_is_peer(thisCtx->getDevice()->_acc);
#else
*canAccessPeer = 0;
#endif
@@ -60,33 +67,32 @@ hipError_t hipDeviceCanAccessPeer (int* canAccessPeer, int deviceId, int peerDe
//---
// Disable visibility of this device into memory allocated on peer device.
// Remove this device from peer device peerlist.
hipError_t hipDeviceDisablePeerAccess (int peerDeviceId)
hipError_t hipDeviceDisablePeerAccess (hipCtx_t *peerCtx)
{
HIP_INIT_API(peerDeviceId);
HIP_INIT_API(peerCtx);
hipError_t err = hipSuccess;
auto thisDevice = ihipGetTlsDefaultCtx();
auto peerDevice = ihipGetDevice(peerDeviceId);
if ((thisDevice != NULL) && (peerDevice != NULL)) {
auto thisCtx = ihipGetTlsDefaultCtx();
if ((thisCtx != NULL) && (peerCtx != NULL)) {
#if USE_PEER_TO_PEER>=2
// Return true if thisDevice can access peerDevice's memory:
bool canAccessPeer = peerDevice->_acc.get_is_peer(thisDevice->_acc);
// Return true if thisCtx can access peerCtx's memory:
bool canAccessPeer = peerCtx->getDevice()->_acc.get_is_peer(thisCtx->getDevice()->_acc);
#else
bool canAccessPeer = 0;
#endif
if (! canAccessPeer) {
err = hipErrorInvalidDevice; // P2P not allowed between these devices.
} else if (thisDevice == peerDevice) {
} else if (thisCtx == peerCtx) {
err = hipErrorInvalidDevice; // Can't disable peer access to self.
} else {
LockedAccessor_DeviceCrit_t peerCrit(peerDevice->criticalData());
bool changed = peerCrit->removePeer(thisDevice);
LockedAccessor_CtxCrit_t peerCrit(peerCtx->criticalData());
bool changed = peerCrit->removePeer(thisCtx);
if (changed) {
#if USE_PEER_TO_PEER>=3
// Update the peers for all memory already saved in the tracker:
am_memtracker_update_peers(peerDevice->_acc, peerCrit->peerCnt(), peerCrit->peerAgents());
am_memtracker_update_peers(peerCtx->getDevice()->_acc, peerCrit->peerCnt(), peerCrit->peerAgents());
#endif
} else {
err = hipErrorPeerAccessNotEnabled; // never enabled P2P access.
@@ -103,24 +109,23 @@ hipError_t hipDeviceDisablePeerAccess (int peerDeviceId)
//---
// Allow the current device to see all memory allocated on peerDevice.
// This should add this device to the peer-device peer list.
hipError_t hipDeviceEnablePeerAccess (int peerDeviceId, unsigned int flags)
hipError_t hipDeviceEnablePeerAccess (hipCtx_t *peerCtx, unsigned int flags)
{
HIP_INIT_API(peerDeviceId, flags);
HIP_INIT_API(peerCtx, flags);
hipError_t err = hipSuccess;
if (flags != 0) {
err = hipErrorInvalidValue;
} else {
auto thisDevice = ihipGetTlsDefaultCtx();
auto peerDevice = ihipGetDevice(peerDeviceId);
if (thisDevice == peerDevice) {
auto thisCtx = ihipGetTlsDefaultCtx();
if (thisCtx == peerCtx) {
err = hipErrorInvalidDevice; // Can't enable peer access to self.
} else if ((thisDevice != NULL) && (peerDevice != NULL)) {
LockedAccessor_DeviceCrit_t peerCrit(peerDevice->criticalData());
bool isNewPeer = peerCrit->addPeer(thisDevice);
} else if ((thisCtx != NULL) && (peerCtx != NULL)) {
LockedAccessor_CtxCrit_t peerCrit(peerCtx->criticalData());
bool isNewPeer = peerCrit->addPeer(thisCtx);
if (isNewPeer) {
#if USE_PEER_TO_PEER>=3
am_memtracker_update_peers(peerDevice->_acc, peerCrit->peerCnt(), peerCrit->peerAgents());
am_memtracker_update_peers(peerCtx->getDevice()->_acc, peerCrit->peerCnt(), peerCrit->peerAgents());
#endif
} else {
err = hipErrorPeerAccessAlreadyEnabled;
@@ -135,20 +140,17 @@ hipError_t hipDeviceEnablePeerAccess (int peerDeviceId, unsigned int flags)
//---
hipError_t hipMemcpyPeer (void* dst, int dstDevice, const void* src, int srcDevice, size_t sizeBytes)
hipError_t hipMemcpyPeer (void* dst, hipCtx_t *dstCtx, const void* src, hipCtx_t *srcCtx, size_t sizeBytes)
{
HIP_INIT_API(dst, dstDevice, src, srcDevice, sizeBytes);
HIP_INIT_API(dst, dstCtx, src, srcCtx, sizeBytes);
// HCC has a unified memory architecture so device specifiers are not required.
return hipMemcpy(dst, src, sizeBytes, hipMemcpyDefault);
};
/**
* This function uses a synchronous copy
*/
//---
hipError_t hipMemcpyPeerAsync (void* dst, int dstDevice, const void* src, int srcDevice, size_t sizeBytes, hipStream_t stream)
hipError_t hipMemcpyPeerAsync (void* dst, hipCtx_t *dstDevice, const void* src, hipCtx_t *srcDevice, size_t sizeBytes, hipStream_t stream)
{
HIP_INIT_API(dst, dstDevice, src, srcDevice, sizeBytes, stream);
// HCC has a unified memory architecture so device specifiers are not required.
@@ -156,6 +158,49 @@ hipError_t hipMemcpyPeerAsync (void* dst, int dstDevice, const void* src, int
};
//=============================================================================
// These are the flavors that accept integer deviceIDs.
// Implementations map these to primary contexts and call the internal functions above.
//=============================================================================
hipError_t hipDeviceCanAccessPeer (int* canAccessPeer, int deviceId, int peerDeviceId)
{
HIP_INIT_API(canAccessPeer, deviceId, peerDeviceId);
return hipDeviceCanAccessPeer(canAccessPeer, ihipGetPrimaryCtx(deviceId), ihipGetPrimaryCtx(peerDeviceId));
}
hipError_t hipDeviceDisablePeerAccess (int peerDeviceId)
{
HIP_INIT_API(peerDeviceId);
return hipDeviceDisablePeerAccess(ihipGetPrimaryCtx(peerDeviceId));
}
hipError_t hipDeviceEnablePeerAccess (int peerDeviceId, unsigned int flags)
{
HIP_INIT_API(peerDeviceId, flags);
return hipDeviceEnablePeerAccess(ihipGetPrimaryCtx(peerDeviceId), flags);
}
hipError_t hipMemcpyPeer (void* dst, int dstDevice, const void* src, int srcDevice, size_t sizeBytes)
{
HIP_INIT_API(dst, dstDevice, src, srcDevice, sizeBytes);
return hipMemcpyPeer(dst, ihipGetPrimaryCtx(dstDevice), src, ihipGetPrimaryCtx(srcDevice), sizeBytes);
}
hipError_t hipMemcpyPeerAsync (void* dst, int dstDevice, const void* src, int srcDevice, size_t sizeBytes, hipStream_t stream)
{
HIP_INIT_API(dst, dstDevice, src, srcDevice, sizeBytes, stream);
return hipMemcpyPeerAsync(dst, ihipGetPrimaryCtx(dstDevice), src, ihipGetPrimaryCtx(srcDevice), sizeBytes, stream);
}
/**
* @return #hipSuccess
*/