Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F63211479
TestMemoryPool.hpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, May 18, 12:28
Size
9 KB
Mime Type
text/x-c
Expires
Mon, May 20, 12:28 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
17745500
Attached To
rLAMMPS lammps
TestMemoryPool.hpp
View Options
/*
//@HEADER
// ************************************************************************
//
// Kokkos v. 2.0
// Copyright (2014) Sandia Corporation
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the Corporation nor the names of the
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Questions? Contact H. Carter Edwards (hcedwar@sandia.gov)
//
// ************************************************************************
//@HEADER
*/
#ifndef KOKKOS_UNITTEST_MEMPOOL_HPP
#define KOKKOS_UNITTEST_MEMPOOL_HPP
#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <impl/Kokkos_Timer.hpp>
namespace
TestMemoryPool
{
template
<
typename
MemSpace
=
Kokkos
::
HostSpace
>
void
test_host_memory_pool_stats
()
{
typedef
typename
MemSpace
::
execution_space
Space
;
typedef
typename
Kokkos
::
MemoryPool
<
Space
>
MemPool
;
const
size_t
MemoryCapacity
=
32000
;
const
size_t
MinBlockSize
=
64
;
const
size_t
MaxBlockSize
=
1024
;
const
size_t
SuperBlockSize
=
4096
;
MemPool
pool
(
MemSpace
()
,
MemoryCapacity
,
MinBlockSize
,
MaxBlockSize
,
SuperBlockSize
);
{
typename
MemPool
::
usage_statistics
stats
;
pool
.
get_usage_statistics
(
stats
);
ASSERT_LE
(
MemoryCapacity
,
stats
.
capacity_bytes
);
ASSERT_LE
(
MinBlockSize
,
stats
.
min_block_bytes
);
ASSERT_LE
(
MaxBlockSize
,
stats
.
max_block_bytes
);
ASSERT_LE
(
SuperBlockSize
,
stats
.
superblock_bytes
);
}
void
*
p0064
=
pool
.
allocate
(
64
);
void
*
p0128
=
pool
.
allocate
(
128
);
void
*
p0256
=
pool
.
allocate
(
256
);
void
*
p1024
=
pool
.
allocate
(
1024
);
// Aborts because exceeds max block size:
// void * p2048 = pool.allocate(2048);
ASSERT_NE
(
p0064
,
(
void
*
)
0
);
ASSERT_NE
(
p0128
,
(
void
*
)
0
);
ASSERT_NE
(
p0256
,
(
void
*
)
0
);
ASSERT_NE
(
p1024
,
(
void
*
)
0
);
pool
.
deallocate
(
p0064
,
64
);
pool
.
deallocate
(
p0128
,
128
);
pool
.
deallocate
(
p0256
,
256
);
pool
.
deallocate
(
p1024
,
1024
);
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
template
<
class
DeviceType
>
struct
TestMemoryPool_Functor
{
typedef
Kokkos
::
View
<
uintptr_t
*
,
DeviceType
>
ptrs_type
;
typedef
Kokkos
::
MemoryPool
<
DeviceType
>
pool_type
;
pool_type
pool
;
ptrs_type
ptrs
;
TestMemoryPool_Functor
(
const
pool_type
&
arg_pool
,
size_t
n
)
:
pool
(
arg_pool
)
,
ptrs
(
"ptrs"
,
n
)
{}
// Specify reduction argument value_type to avoid
// confusion with tag-dispatch.
using
value_type
=
long
;
struct
TagAlloc
{};
KOKKOS_INLINE_FUNCTION
void
operator
()(
TagAlloc
,
int
i
,
long
&
update
)
const
noexcept
{
unsigned
alloc_size
=
32
*
(
1
+
(
i
%
5
));
ptrs
(
i
)
=
(
uintptr_t
)
pool
.
allocate
(
alloc_size
);
if
(
ptrs
(
i
)
)
{
++
update
;
}
}
struct
TagDealloc
{};
KOKKOS_INLINE_FUNCTION
void
operator
()(
TagDealloc
,
int
i
,
long
&
update
)
const
noexcept
{
if
(
ptrs
(
i
)
&&
(
0
==
i
%
3
)
)
{
unsigned
alloc_size
=
32
*
(
1
+
(
i
%
5
));
pool
.
deallocate
(
(
void
*
)
ptrs
(
i
)
,
alloc_size
);
ptrs
(
i
)
=
0
;
++
update
;
}
}
struct
TagRealloc
{};
KOKKOS_INLINE_FUNCTION
void
operator
()(
TagRealloc
,
int
i
,
long
&
update
)
const
noexcept
{
if
(
0
==
ptrs
(
i
)
)
{
unsigned
alloc_size
=
32
*
(
1
+
(
i
%
5
));
ptrs
(
i
)
=
(
uintptr_t
)
pool
.
allocate
(
alloc_size
);
if
(
ptrs
(
i
)
)
{
++
update
;
}
}
}
struct
TagMixItUp
{};
KOKKOS_INLINE_FUNCTION
void
operator
()(
TagMixItUp
,
int
i
,
long
&
update
)
const
noexcept
{
if
(
ptrs
(
i
)
&&
(
0
==
i
%
3
)
)
{
unsigned
alloc_size
=
32
*
(
1
+
(
i
%
5
));
pool
.
deallocate
(
(
void
*
)
ptrs
(
i
)
,
alloc_size
);
ptrs
(
i
)
=
(
uintptr_t
)
pool
.
allocate
(
alloc_size
);
if
(
ptrs
(
i
)
)
{
++
update
;
}
}
}
};
template
<
class
PoolType
>
void
print_memory_pool_stats
(
typename
PoolType
::
usage_statistics
const
&
stats
)
{
std
::
cout
<<
"MemoryPool {"
<<
std
::
endl
<<
" bytes capacity = "
<<
stats
.
capacity_bytes
<<
std
::
endl
<<
" bytes used = "
<<
stats
.
consumed_bytes
<<
std
::
endl
<<
" bytes reserved = "
<<
stats
.
reserved_bytes
<<
std
::
endl
<<
" bytes free = "
<<
(
stats
.
capacity_bytes
-
(
stats
.
consumed_bytes
+
stats
.
reserved_bytes
)
)
<<
std
::
endl
<<
" alloc used = "
<<
stats
.
consumed_blocks
<<
std
::
endl
<<
" alloc reserved = "
<<
stats
.
reserved_blocks
<<
std
::
endl
<<
" super used = "
<<
stats
.
consumed_superblocks
<<
std
::
endl
<<
" super reserved = "
<<
(
stats
.
capacity_superblocks
-
stats
.
consumed_superblocks
)
<<
std
::
endl
<<
"}"
<<
std
::
endl
;
}
template
<
class
DeviceType
>
void
test_memory_pool_v2
(
const
bool
print_statistics
,
const
bool
print_superblocks
)
{
typedef
typename
DeviceType
::
memory_space
memory_space
;
typedef
typename
DeviceType
::
execution_space
execution_space
;
typedef
Kokkos
::
MemoryPool
<
DeviceType
>
pool_type
;
typedef
TestMemoryPool_Functor
<
DeviceType
>
functor_type
;
typedef
typename
functor_type
::
TagAlloc
TagAlloc
;
typedef
typename
functor_type
::
TagDealloc
TagDealloc
;
typedef
typename
functor_type
::
TagRealloc
TagRealloc
;
typedef
typename
functor_type
::
TagMixItUp
TagMixItUp
;
const
size_t
total_alloc_size
=
10000000
;
const
unsigned
min_block_size
=
64
;
const
unsigned
max_block_size
=
256
;
const
long
nfill
=
70000
;
for
(
uint32_t
k
=
0
,
min_superblock_size
=
10000
;
k
<
3
;
++
k
,
min_superblock_size
*=
10
)
{
typename
pool_type
::
usage_statistics
stats
;
pool_type
pool
(
memory_space
()
,
total_alloc_size
,
min_block_size
,
max_block_size
,
min_superblock_size
);
functor_type
functor
(
pool
,
nfill
);
long
result
=
0
;
long
ndel
=
0
;
Kokkos
::
parallel_reduce
(
Kokkos
::
RangePolicy
<
execution_space
,
TagAlloc
>
(
0
,
nfill
)
,
functor
,
result
);
pool
.
get_usage_statistics
(
stats
);
const
int
fill_error
=
(
nfill
!=
result
)
||
(
nfill
!=
long
(
stats
.
consumed_blocks
)
);
if
(
fill_error
||
print_statistics
)
print_memory_pool_stats
<
pool_type
>
(
stats
);
if
(
fill_error
||
print_superblocks
)
pool
.
print_state
(
std
::
cout
);
ASSERT_EQ
(
nfill
,
result
);
ASSERT_EQ
(
nfill
,
long
(
stats
.
consumed_blocks
)
);
Kokkos
::
parallel_reduce
(
Kokkos
::
RangePolicy
<
execution_space
,
TagDealloc
>
(
0
,
nfill
)
,
functor
,
ndel
);
pool
.
get_usage_statistics
(
stats
);
const
int
del_error
=
(
nfill
-
ndel
)
!=
long
(
stats
.
consumed_blocks
);
if
(
del_error
||
print_statistics
)
print_memory_pool_stats
<
pool_type
>
(
stats
);
if
(
del_error
||
print_superblocks
)
pool
.
print_state
(
std
::
cout
);
ASSERT_EQ
(
(
nfill
-
ndel
)
,
long
(
stats
.
consumed_blocks
)
);
Kokkos
::
parallel_reduce
(
Kokkos
::
RangePolicy
<
execution_space
,
TagRealloc
>
(
0
,
nfill
)
,
functor
,
result
);
pool
.
get_usage_statistics
(
stats
);
const
int
refill_error
=
(
ndel
!=
result
)
||
(
nfill
!=
long
(
stats
.
consumed_blocks
)
);
if
(
refill_error
||
print_statistics
)
print_memory_pool_stats
<
pool_type
>
(
stats
);
if
(
refill_error
||
print_superblocks
)
pool
.
print_state
(
std
::
cout
);
ASSERT_EQ
(
ndel
,
result
);
ASSERT_EQ
(
nfill
,
long
(
stats
.
consumed_blocks
)
);
Kokkos
::
parallel_reduce
(
Kokkos
::
RangePolicy
<
execution_space
,
TagMixItUp
>
(
0
,
nfill
)
,
functor
,
result
);
pool
.
get_usage_statistics
(
stats
);
const
int
mix_error
=
(
ndel
!=
result
)
||
(
nfill
!=
long
(
stats
.
consumed_blocks
)
);
if
(
mix_error
||
print_statistics
)
print_memory_pool_stats
<
pool_type
>
(
stats
);
if
(
mix_error
||
print_superblocks
)
pool
.
print_state
(
std
::
cout
);
ASSERT_EQ
(
ndel
,
result
);
ASSERT_EQ
(
nfill
,
long
(
stats
.
consumed_blocks
)
);
}
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
}
// namespace TestMemoryPool {
namespace
Test
{
TEST_F
(
TEST_CATEGORY
,
memory_pool
)
{
TestMemoryPool
::
test_host_memory_pool_stats
<>
();
TestMemoryPool
::
test_memory_pool_v2
<
TEST_EXECSPACE
>
(
false
,
false
);
}
}
#endif
Event Timeline
Log In to Comment