deepspeed_aio_utils.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. Copyright 2020 The Microsoft DeepSpeed Team
  3. Licensed under the MIT license.
  4. Functionality for swapping optimizer tensors to/from (NVMe) storage devices.
  5. */
  6. #include <cmath>
  7. #include "deepspeed_aio_utils.h"
  8. using namespace std;
  9. const int c_block_size = 128 * 1024;
  10. const int c_io_queue_depth = 8;
  11. io_xfer_ctxt::io_xfer_ctxt(const int fd,
  12. const long long int file_offset,
  13. const long long int num_bytes,
  14. const void* buffer)
  15. : _fd(fd), _base_offset(file_offset), _mem_buffer(buffer), _num_bytes(num_bytes)
  16. {
  17. }
  18. io_prep_context::io_prep_context(const bool read_op,
  19. const std::unique_ptr<io_xfer_ctxt>& xfer_ctxt,
  20. const size_t block_size,
  21. const std::vector<struct iocb*>* iocbs)
  22. : _read_op(read_op), _xfer_ctxt(xfer_ctxt), _block_size(block_size), _iocbs(iocbs)
  23. {
  24. }
  25. void io_prep_context::prep_iocbs(const int n_iocbs,
  26. const size_t num_bytes,
  27. const void* start_buffer,
  28. const long long int start_offset)
  29. {
  30. assert(static_cast<size_t>(n_iocbs) <= _iocbs->size());
  31. for (auto i = 0; i < n_iocbs; ++i) {
  32. const auto shift = i * _block_size;
  33. const auto xfer_buffer = (char*)start_buffer + _xfer_ctxt->_base_offset + shift;
  34. const auto xfer_offset = _xfer_ctxt->_base_offset + start_offset + shift;
  35. auto byte_count = _block_size;
  36. if ((shift + _block_size) > num_bytes) { byte_count = num_bytes - shift; }
  37. if (_read_op) {
  38. io_prep_pread(_iocbs->at(i), _xfer_ctxt->_fd, xfer_buffer, byte_count, xfer_offset);
  39. } else {
  40. io_prep_pwrite(_iocbs->at(i), _xfer_ctxt->_fd, xfer_buffer, byte_count, xfer_offset);
  41. }
  42. }
  43. }
  44. io_prep_generator::io_prep_generator(const bool read_op,
  45. const std::unique_ptr<io_xfer_ctxt>& xfer_ctxt,
  46. const size_t block_size)
  47. : _read_op(read_op),
  48. _xfer_ctxt(xfer_ctxt),
  49. _block_size(block_size),
  50. _remaining_bytes(xfer_ctxt->_num_bytes),
  51. _next_iocb_index(0)
  52. {
  53. _num_io_blocks =
  54. static_cast<long long int>(ceil(static_cast<double>(xfer_ctxt->_num_bytes) / block_size));
  55. _remaining_io_blocks = _num_io_blocks;
  56. }
  57. int io_prep_generator::prep_iocbs(const int n_iocbs, std::vector<struct iocb*>* iocbs)
  58. {
  59. if ((_remaining_bytes) == 0 || (_remaining_io_blocks == 0)) {
  60. assert(static_cast<long long int>(_remaining_bytes) == _remaining_io_blocks);
  61. return 0;
  62. }
  63. assert(static_cast<size_t>(n_iocbs) <= iocbs->size());
  64. auto actual_n_iocbs = min(static_cast<long long int>(n_iocbs), _remaining_io_blocks);
  65. for (auto i = 0; i < actual_n_iocbs; ++i, ++_next_iocb_index) {
  66. const auto xfer_offset = _xfer_ctxt->_base_offset + (_next_iocb_index * _block_size);
  67. const auto xfer_buffer = (char*)_xfer_ctxt->_mem_buffer + xfer_offset;
  68. const auto num_bytes = min(static_cast<long long int>(_block_size), _remaining_bytes);
  69. if (_read_op) {
  70. io_prep_pread(iocbs->at(i), _xfer_ctxt->_fd, xfer_buffer, num_bytes, xfer_offset);
  71. } else {
  72. io_prep_pwrite(iocbs->at(i), _xfer_ctxt->_fd, xfer_buffer, num_bytes, xfer_offset);
  73. }
  74. _remaining_bytes -= num_bytes;
  75. }
  76. _remaining_io_blocks -= actual_n_iocbs;
  77. return actual_n_iocbs;
  78. }
  79. int get_file_size(const char* filename, long long int& size)
  80. {
  81. struct stat st;
  82. if (stat(filename, &st) == -1) { return -1; }
  83. size = st.st_size;
  84. return 0;
  85. }
  86. void* ds_page_aligned_alloc(const size_t size, const bool lock)
  87. {
  88. void* ptr;
  89. int retval;
  90. retval = posix_memalign(&ptr, (size_t)sysconf(_SC_PAGESIZE), size);
  91. if (retval) { return nullptr; }
  92. if (lock == false) { return ptr; }
  93. auto mlock_ret = mlock(ptr, size);
  94. if (mlock_ret != 0) {
  95. auto mlock_error = errno;
  96. printf("mlock failed with %d %s\n", mlock_error, strerror(mlock_error));
  97. free(ptr);
  98. return nullptr;
  99. }
  100. return ptr;
  101. }