threading.h 1.98 KB
Newer Older
1
2
3
4
/*!
 * Copyright (c) 2016 Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See LICENSE file in the project root for license information.
 */
Guolin Ke's avatar
Guolin Ke committed
5
6
7
#ifndef LIGHTGBM_UTILS_THREADING_H_
#define LIGHTGBM_UTILS_THREADING_H_

8
#include <LightGBM/utils/openmp_wrapper.h>
Guolin Ke's avatar
Guolin Ke committed
9
10

#include <functional>
11
#include <vector>
Guolin Ke's avatar
Guolin Ke committed
12
13
14
15

namespace LightGBM {

class Threading {
Nikita Titov's avatar
Nikita Titov committed
16
 public:
Guolin Ke's avatar
Guolin Ke committed
17
18
19
  template <typename INDEX_T>
  static inline void BlockInfo(INDEX_T cnt, INDEX_T min_cnt_per_block,
                               int* out_nblock, INDEX_T* block_size) {
Guolin Ke's avatar
Guolin Ke committed
20
    int num_threads = 1;
Guolin Ke's avatar
Guolin Ke committed
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#pragma omp parallel
#pragma omp master
    { num_threads = omp_get_num_threads(); }
    BlockInfo<INDEX_T>(num_threads, cnt, min_cnt_per_block, out_nblock,
                       block_size);
  }
  template <typename INDEX_T>
  static inline void BlockInfo(int num_threads, INDEX_T cnt,
                               INDEX_T min_cnt_per_block, int* out_nblock,
                               INDEX_T* block_size) {
    *out_nblock = std::min<int>(
        num_threads,
        static_cast<int>((cnt + min_cnt_per_block - 1) / min_cnt_per_block));
    if (*out_nblock > 1) {
      *block_size = SIZE_ALIGNED((cnt + (*out_nblock) - 1) / (*out_nblock));
    } else {
      *block_size = cnt;
Guolin Ke's avatar
Guolin Ke committed
38
    }
Guolin Ke's avatar
Guolin Ke committed
39
40
41
42
43
44
45
46
  }
  template <typename INDEX_T>
  static inline int For(
      INDEX_T start, INDEX_T end, INDEX_T min_block_size,
      const std::function<void(int, INDEX_T, INDEX_T)>& inner_fun) {
    int n_block = 1;
    INDEX_T num_inner = end - start;
    BlockInfo<INDEX_T>(end - start, min_block_size, &n_block, &num_inner);
47
    OMP_INIT_EX();
Guolin Ke's avatar
Guolin Ke committed
48
49
#pragma omp parallel for schedule(static, 1)
    for (int i = 0; i < n_block; ++i) {
50
      OMP_LOOP_EX_BEGIN();
Guolin Ke's avatar
Guolin Ke committed
51
      INDEX_T inner_start = start + num_inner * i;
Guolin Ke's avatar
Guolin Ke committed
52
53
      INDEX_T inner_end = std::min(end, inner_start + num_inner);
      inner_fun(i, inner_start, inner_end);
54
      OMP_LOOP_EX_END();
Guolin Ke's avatar
Guolin Ke committed
55
    }
56
    OMP_THROW_EX();
Guolin Ke's avatar
Guolin Ke committed
57
    return n_block;
Guolin Ke's avatar
Guolin Ke committed
58
59
60
61
62
  }
};

}   // namespace LightGBM

Guolin Ke's avatar
Guolin Ke committed
63
#endif   // LightGBM_UTILS_THREADING_H_