KFDEvictTest: change buffer size and add GFX vram allocation

This is to coordinate kfd kernel vram limit change, and adding
GFX vram allocation with submission of command nop is to
trigger eviction.



Change-Id: I18615cd13cfde034aae09c188ae3a82babde97b9
Signed-off-by: Eric Huang <JinHuiEric.Huang@amd.com>


[ROCm/ROCR-Runtime commit: 3167e3b964]
Cette révision appartient à :
Eric Huang
2018-08-01 14:22:17 -04:00
révisé par JinHuiEric Huang
Parent 7162162847
révision 6f330cf658
2 fichiers modifiés avec 197 ajouts et 30 suppressions
+194 -29
Voir le fichier
@@ -34,33 +34,13 @@
#define ALLOCATE_BUF_SIZE_MB (64)
#define ALLOCATE_RETRY_TIMES (3)
HSAint32 KFDEvictTest::GetBufferCounter(HSAuint64 vramSize, HSAuint64 vramBufSize) {
HSAuint64 vramBufSizeInPages = vramBufSize >> PAGE_SHIFT;
HSAuint64 sysMemSize = GetSysMemSize();
HSAuint64 size, sizeInPages;
HSAuint32 count;
LOG() << "Found System RAM of " << std::dec << (sysMemSize >> 20) << "MB" << std::endl;
/* use one third of total system memory for eviction buffer to test
* limit max allocate size to duoble of vramSize
* count is zero if not enough memory (sysMemSize/3 + vramSize) < (vramBufSize * N_PROCESSES)
*/
size = sysMemSize/3 + vramSize;
size = size > vramSize<<1 ? vramSize<<1 : size;
sizeInPages = size >> PAGE_SHIFT;
count = sizeInPages / (vramBufSizeInPages * N_PROCESSES);
return count;
}
void KFDEvictTest::AllocBuffers(HSAuint32 defaultGPUNode, HSAuint32 count, HSAuint64 vramBufSize,
std::vector<void *> &pBuffers) {
HSAuint64 totalMB;
totalMB = N_PROCESSES*count*(vramBufSize>>20);
if (m_IsParent) {
LOG() << "Testing " << N_PROCESSES << "*" << count << "*" << (vramBufSize>>20) << "(="<< totalMB << ")MB" << std::endl;
LOG() << "Allocating " << N_PROCESSES << "*" << count << "*" << (vramBufSize>>20) << "(="<< totalMB << ")MB VRAM in KFD" << std::endl;
}
HSAKMT_STATUS ret;
@@ -106,6 +86,164 @@ void KFDEvictTest::FreeBuffers(std::vector<void *> &pBuffers, HSAuint64 vramBufS
}
}
void KFDEvictTest::AllocAmdgpuBo(int rn, HSAuint64 vramBufSize, amdgpu_bo_handle &handle) {
struct amdgpu_bo_alloc_request alloc;
alloc.alloc_size = vramBufSize / N_PROCESSES;
alloc.phys_alignment = PAGE_SIZE;
alloc.preferred_heap = AMDGPU_GEM_DOMAIN_VRAM;
alloc.flags = AMDGPU_GEM_CREATE_VRAM_CLEARED;
if (m_IsParent) {
LOG() << "Allocating " << N_PROCESSES << "*" << (vramBufSize >> 20) / N_PROCESSES << "(=" << (vramBufSize >> 20) << ")MB VRAM in GFX" << std::endl;
}
ASSERT_EQ(0, amdgpu_bo_alloc(m_RenderNodes[rn].device_handle, &alloc, &handle));
}
void KFDEvictTest::FreeAmdgpuBo(amdgpu_bo_handle handle) {
ASSERT_EQ(0, amdgpu_bo_free(handle));
}
static int
amdgpu_bo_alloc_and_map(amdgpu_device_handle dev, unsigned size,
unsigned alignment, unsigned heap, uint64_t flags,
amdgpu_bo_handle *bo, void **cpu, uint64_t *mc_address,
amdgpu_va_handle *va_handle)
{
struct amdgpu_bo_alloc_request request = {};
amdgpu_bo_handle buf_handle;
amdgpu_va_handle handle;
uint64_t vmc_addr;
int r;
request.alloc_size = size;
request.phys_alignment = alignment;
request.preferred_heap = heap;
request.flags = flags;
r = amdgpu_bo_alloc(dev, &request, &buf_handle);
if (r)
return r;
r = amdgpu_va_range_alloc(dev,
amdgpu_gpu_va_range_general,
size, alignment, 0, &vmc_addr,
&handle, 0);
if (r)
goto error_va_alloc;
r = amdgpu_bo_va_op(buf_handle, 0, size, vmc_addr, 0, AMDGPU_VA_OP_MAP);
if (r)
goto error_va_map;
r = amdgpu_bo_cpu_map(buf_handle, cpu);
if (r)
goto error_cpu_map;
*bo = buf_handle;
*mc_address = vmc_addr;
*va_handle = handle;
return 0;
error_cpu_map:
amdgpu_bo_cpu_unmap(buf_handle);
error_va_map:
amdgpu_bo_va_op(buf_handle, 0, size, vmc_addr, 0, AMDGPU_VA_OP_UNMAP);
error_va_alloc:
amdgpu_bo_free(buf_handle);
return r;
}
static inline int
amdgpu_bo_unmap_and_free(amdgpu_bo_handle bo, amdgpu_va_handle va_handle,
uint64_t mc_addr, uint64_t size)
{
amdgpu_bo_cpu_unmap(bo);
amdgpu_bo_va_op(bo, 0, size, mc_addr, 0, AMDGPU_VA_OP_UNMAP);
amdgpu_va_range_free(va_handle);
amdgpu_bo_free(bo);
return 0;
}
static inline int
amdgpu_get_bo_list(amdgpu_device_handle dev, amdgpu_bo_handle bo1,
amdgpu_bo_handle bo2, amdgpu_bo_list_handle *list)
{
amdgpu_bo_handle resources[] = {bo1, bo2};
return amdgpu_bo_list_create(dev, bo2 ? 2 : 1, resources, NULL, list);
}
void KFDEvictTest::AmdgpuCommandSubmissionComputeNop(int rn) {
amdgpu_context_handle contextHandle;
amdgpu_bo_handle ibResultHandle;
void *ibResultCpu;
uint64_t ibResultMcAddress;
struct amdgpu_cs_request ibsRequest;
struct amdgpu_cs_ib_info ibInfo;
struct amdgpu_cs_fence fenceStatus;
amdgpu_bo_list_handle boList;
amdgpu_va_handle vaHandle;
uint32_t *ptr;
uint32_t expired;
ASSERT_EQ(0, amdgpu_cs_ctx_create(m_RenderNodes[rn].device_handle, &contextHandle));
ASSERT_EQ(0, amdgpu_bo_alloc_and_map(m_RenderNodes[rn].device_handle,
PAGE_SIZE, PAGE_SIZE,
AMDGPU_GEM_DOMAIN_GTT, 0,
&ibResultHandle, &ibResultCpu,
&ibResultMcAddress, &vaHandle));
ASSERT_EQ(0, amdgpu_get_bo_list(m_RenderNodes[rn].device_handle, ibResultHandle, NULL,
&boList));
/* Fill Nop cammands in IB */
ptr = (uint32_t *)ibResultCpu;
for (int i = 0; i < 16; i++)
ptr[i] = 0xffff1000;
memset(&ibInfo, 0, sizeof(struct amdgpu_cs_ib_info));
ibInfo.ib_mc_address = ibResultMcAddress;
ibInfo.size = 16;
memset(&ibsRequest, 0, sizeof(struct amdgpu_cs_request));
ibsRequest.ip_type = AMDGPU_HW_IP_COMPUTE;
ibsRequest.ring = 0;
ibsRequest.number_of_ibs = 1;
ibsRequest.ibs = &ibInfo;
ibsRequest.resources = boList;
ibsRequest.fence_info.handle = NULL;
memset(&fenceStatus, 0, sizeof(struct amdgpu_cs_fence));
for (int i = 0; i < ALLOCATE_RETRY_TIMES; i++) {
ASSERT_EQ(0, amdgpu_cs_submit(contextHandle, 0, &ibsRequest, 1));
sleep(1);
}
fenceStatus.context = contextHandle;
fenceStatus.ip_type = AMDGPU_HW_IP_COMPUTE;
fenceStatus.ip_instance = 0;
fenceStatus.ring = 0;
fenceStatus.fence = ibsRequest.seq_no;
ASSERT_EQ(0, amdgpu_cs_query_fence_status(&fenceStatus,
g_TestTimeOut,
0, &expired));
ASSERT_EQ(0, amdgpu_bo_list_destroy(boList));
ASSERT_EQ(0, amdgpu_bo_unmap_and_free(ibResultHandle, vaHandle,
ibResultMcAddress, PAGE_SIZE));
ASSERT_EQ(0, amdgpu_cs_ctx_free(contextHandle));
}
void KFDEvictTest::ForkChildProcesses(int nprocesses) {
int i;
@@ -196,21 +334,30 @@ TEST_F(KFDEvictTest, BasicTest) {
LOG() << "Found VRAM of " << std::dec << (vramSize >> 20) << "MB" << std::endl;
}
HSAuint32 count = GetBufferCounter(vramSize, vramBufSize);
if (count == 0) {
LOG() << "Not enough system memory, skipping the test" << std::endl;
return;
}
HSAint32 count = vramSize / vramBufSize / N_PROCESSES;
LOG() << "Found System RAM of " << std::dec << (GetSysMemSize() >> 20) << "MB" << std::endl;
/* Fork the child processes */
ForkChildProcesses(N_PROCESSES);
int rn = FindDRMRenderNode(defaultGPUNode);
if (rn < 0) {
LOG() << "Skipping test" << std::endl;
return;
}
std::vector<void *> pBuffers;
AllocBuffers(defaultGPUNode, count, vramBufSize, pBuffers);
/* wait for other processes to finish allocation, then free buffer */
sleep(ALLOCATE_RETRY_TIMES);
/* allocate gfx vram size of at most one third system memory */
HSAuint64 size = GetSysMemSize() / 3 < vramSize ? GetSysMemSize() / 3 : vramSize;
amdgpu_bo_handle handle;
AllocAmdgpuBo(rn, size, handle);
AmdgpuCommandSubmissionComputeNop(rn);
FreeAmdgpuBo(handle);
LOG() << m_psName << "free buffer" << std::endl;
FreeBuffers(pBuffers, vramBufSize);
@@ -388,7 +535,10 @@ TEST_F(KFDEvictTest, QueueTest) {
LOG() << "Found VRAM of " << std::dec << (vramSize >> 20) << "MB." << std::endl;
}
HSAuint32 count = GetBufferCounter(vramSize, vramBufSize);
HSAuint32 count = vramSize / vramBufSize / N_PROCESSES;
LOG() << "Found System RAM of " << std::dec << (GetSysMemSize() >> 20) << "MB" << std::endl;
if (count == 0) {
LOG() << "Not enough system memory, skipping the test" << std::endl;
return;
@@ -401,6 +551,12 @@ TEST_F(KFDEvictTest, QueueTest) {
/* Fork the child processes */
ForkChildProcesses(N_PROCESSES);
int rn = FindDRMRenderNode(defaultGPUNode);
if (rn < 0) {
LOG() << "Skipping test" << std::endl;
return;
}
HsaMemoryBuffer isaBuffer(PAGE_SIZE, defaultGPUNode, true/*zero*/, false/*local*/, true/*exec*/);
HsaMemoryBuffer addrBuffer(PAGE_SIZE, defaultGPUNode);
HsaMemoryBuffer resultBuffer(PAGE_SIZE, defaultGPUNode);
@@ -408,6 +564,13 @@ TEST_F(KFDEvictTest, QueueTest) {
std::vector<void *> pBuffers;
AllocBuffers(defaultGPUNode, count, vramBufSize, pBuffers);
/* allocate gfx vram size of at most one third system memory */
HSAuint64 size = GetSysMemSize() / 3 < vramSize ? GetSysMemSize() / 3 : vramSize;
amdgpu_bo_handle handle;
AllocAmdgpuBo(rn, size, handle);
AmdgpuCommandSubmissionComputeNop(rn);
unsigned int wavefront_num = pBuffers.size();
LOG() << m_psName << "wavefront number " << wavefront_num << std::endl;
@@ -439,6 +602,8 @@ TEST_F(KFDEvictTest, QueueTest) {
dispatch0.SyncWithStatus(120000);
ASSERT_SUCCESS(pm4Queue.Destroy());
FreeAmdgpuBo(handle);
/* LOG() << m_psName << "free buffer" << std::endl; */
/* cleanup */
FreeBuffers(pBuffers, vramBufSize);
+3 -1
Voir le fichier
@@ -54,9 +54,11 @@ class KFDEvictTest : public KFDLocalMemoryTest {
void AllocBuffers(HSAuint32 defaultGPUNode, HSAuint32 count, HSAuint64 vramBufSize,
std::vector<void *> &pBuffers);
void FreeBuffers(std::vector<void *> &pBuffers, HSAuint64 vramBufSize);
void AllocAmdgpuBo(int rn, HSAuint64 vramBufSize, amdgpu_bo_handle &handle);
void FreeAmdgpuBo(amdgpu_bo_handle handle);
void AmdgpuCommandSubmissionComputeNop(int rn);
void ForkChildProcesses(int nprocesses);
void WaitChildProcesses();
HSAint32 GetBufferCounter(HSAuint64 vramSize, HSAuint64 vramBufSize);
protected: // members
std::string m_psName;