Skip to content

Commit ee80b77

Browse files
author
bgawrych
authored
Fix default CPU allocator memory alignment (apache#18885)
* Replace std::malloc to aligned memory allocation in Pooled StorageManager * Add test checking CPU memory alignment * Fix memory allocation success check * Fix sanity
1 parent 344587f commit ee80b77

File tree

4 files changed

+63
-15
lines changed

4 files changed

+63
-15
lines changed

src/common/utils.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,28 @@ inline int GetDefaultDtype(int dtype) {
950950
mshadow::kFloat32;
951951
}
952952

953+
inline bool AlignedMemAlloc(void** ptr, size_t size, size_t alignment) {
954+
#if _MSC_VER
955+
*ptr = _aligned_malloc(size, alignment);
956+
if (*ptr == nullptr)
957+
return false;
958+
#else
959+
int res = posix_memalign(ptr, alignment, size);
960+
if (res != 0)
961+
return false;
962+
#endif
963+
return true;
964+
}
965+
966+
inline void AlignedMemFree(void* ptr) {
967+
#if _MSC_VER
968+
_aligned_free(ptr);
969+
#else
970+
free(ptr);
971+
#endif
972+
}
973+
974+
953975
} // namespace common
954976
} // namespace mxnet
955977
#endif // MXNET_COMMON_UTILS_H_

src/storage/cpu_device_storage.h

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,12 @@ class CPUDeviceStorage {
6060
}; // class CPUDeviceStorage
6161

6262
inline void CPUDeviceStorage::Alloc(Storage::Handle* handle) {
63-
#if _MSC_VER
64-
handle->dptr = _aligned_malloc(handle->size, alignment_);
65-
if (handle->dptr == nullptr) LOG(FATAL) << "Failed to allocate CPU Memory";
66-
#else
67-
int ret = posix_memalign(&handle->dptr, alignment_, handle->size);
68-
if (ret != 0) LOG(FATAL) << "Failed to allocate CPU Memory";
69-
#endif
63+
bool success = mxnet::common::AlignedMemAlloc(&(handle->dptr), handle->size, alignment_);
64+
if (!success) LOG(FATAL) << "Failed to allocate CPU Memory";
7065
}
7166

7267
inline void CPUDeviceStorage::Free(Storage::Handle handle) {
73-
#if _MSC_VER
74-
_aligned_free(handle.dptr);
75-
#else
76-
free(handle.dptr);
77-
#endif
68+
mxnet::common::AlignedMemFree(handle.dptr);
7869
}
7970

8071
} // namespace storage

src/storage/storage_manager_helpers.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ typedef mxnet::common::cuda::DeviceStore CudaDeviceStore;
4242
#endif // _WIN32
4343

4444
#include <tuple>
45+
#include "../common/utils.h"
4546

4647
namespace mxnet {
4748
namespace storage {
@@ -110,10 +111,22 @@ class ContextHelperCPU : public ContextHelper {
110111
}
111112

112113
int Malloc(void **ppNtr, size_t size) const override {
113-
return (*ppNtr = std::malloc(size))? 0 : -1;
114+
bool success = mxnet::common::AlignedMemAlloc(ppNtr, size, alignment_);
115+
return success ? 0 : -1;
114116
}
115117

116-
void Free(void *dptr) const override { std::free(dptr); }
118+
void Free(void *dptr) const override {
119+
mxnet::common::AlignedMemFree(dptr);
120+
}
121+
122+
private:
123+
#if MXNET_USE_MKLDNN == 1
124+
// MKLDNN requires special alignment. 64 is used by the MKLDNN library in
125+
// memory allocation.
126+
static constexpr size_t alignment_ = kMKLDNNAlign;
127+
#else
128+
static constexpr size_t alignment_ = 16;
129+
#endif
117130
};
118131

119132
#if MXNET_USE_CUDA
@@ -155,7 +168,6 @@ class ContextHelperPinned : public ContextHelperGPU {
155168
#else
156169
typedef ContextHelperCPU ContextHelperPinned;
157170
#endif
158-
159171
} // namespace storage
160172
} // namespace mxnet
161173

tests/cpp/storage/storage_test.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,29 @@ TEST(Storage, Basic_CPU) {
4747
storage->Free(handle);
4848
}
4949

50+
TEST(Storage, CPU_MemAlign) {
51+
#if MXNET_USE_MKLDNN == 1
52+
// MKLDNN requires special alignment. 64 is used by the MKLDNN library in
53+
// memory allocation.
54+
static constexpr size_t alignment_ = mxnet::kMKLDNNAlign;
55+
#else
56+
static constexpr size_t alignment_ = 16;
57+
#endif
58+
59+
auto&& storage = mxnet::Storage::Get();
60+
mxnet::Context context_cpu = mxnet::Context::CPU(0);
61+
62+
for (int i = 0; i < 5; ++i) {
63+
const size_t kSize = (std::rand() % 1024) + 1;
64+
auto&& handle = storage->Alloc(kSize, context_cpu);
65+
EXPECT_EQ(handle.ctx, context_cpu);
66+
EXPECT_EQ(handle.size, kSize);
67+
EXPECT_EQ(reinterpret_cast<intptr_t>(handle.dptr) % alignment_, 0);
68+
storage->Free(handle);
69+
}
70+
}
71+
72+
5073
#if MXNET_USE_CUDA
5174
TEST(Storage_GPU, Basic_GPU) {
5275
if (mxnet::test::unitTestsWithCuda) {

0 commit comments

Comments
 (0)