kernel_launch.hpp 3.62 KB
Newer Older
carlushuang's avatar
carlushuang committed
1
2
3
4
5
6
7
8
// SPDX-License-Identifier: MIT
// Copyright (c) 2018-2023, Advanced Micro Devices, Inc. All rights reserved.

#pragma once

#include "ck_tile/core/config.hpp"
#include "ck_tile/host/stream_config.hpp"
#include "ck_tile/host/hip_check_error.hpp"
9
#include "ck_tile/host/timer.hpp"
carlushuang's avatar
carlushuang committed
10
11
12
13
14
15
16
17
#include <hip/hip_runtime.h>
#include <cstddef>

namespace ck_tile {
template <int MaxThreadPerBlock, int MinBlockPerCu, typename Kernel, typename... Args>
#if CK_TILE_USE_LAUNCH_BOUNDS
__launch_bounds__(MaxThreadPerBlock, MinBlockPerCu)
#endif
18
    __global__ void kentry(Args... args)
carlushuang's avatar
carlushuang committed
19
{
20
    Kernel{}(args...);
carlushuang's avatar
carlushuang committed
21
22
}

23
24
25
26
27
28
29
30
31
32
33
34
35
//
// return a anonymous functor(lambda) to be called later
// the KernelImpl should be a class without non-static data member, or let's say
// can be instantiate with "KernelImpl{}"
//
// the "static __device__ operator()(some_arg)" is the entry point of KernelImpl
//
template <int MaxThreadPerBlock = CK_TILE_MAX_THREAD_PER_BLOCK,
          int MinBlockPerCu     = CK_TILE_MIN_BLOCK_PER_CU,
          typename KernelImpl,
          typename... Args>
CK_TILE_HOST auto
make_kernel(KernelImpl /*f*/, dim3 grid_dim, dim3 block_dim, std::size_t lds_byte, Args... args)
carlushuang's avatar
carlushuang committed
36
{
37
    const auto kernel = kentry<MaxThreadPerBlock, MinBlockPerCu, KernelImpl, Args...>;
carlushuang's avatar
carlushuang committed
38

39
    return [=](const stream_config& s) {
carlushuang's avatar
carlushuang committed
40
        kernel<<<grid_dim, block_dim, lds_byte, s.stream_id_>>>(args...);
41
    };
carlushuang's avatar
carlushuang committed
42
43
}

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// clang-format off
/*
 * launch_kernel()
 *
 * this is the function to launch arbitrary number of kernels with optional timer(selected by stream_config)
 * the callables should have signature as "operator()(const stream_config& s){ ... }" to call
 * 
 * the simplest way is pass in a lambda function, with "[=](const stream_config& s){ call_your_kernel_here() }"
 * as signature, for the callable (pay attention to the capture list)
 * 
 * e.g.
 *  ck_tile::launch_kernel(s,
 *                      [=](const stream_config& s){ hipMemset(ptr, 0, size) },
 *                      [=](const stream_config& s){ some_kernel<<<grids, blocks>>>(arg); }
 *                      );
 * 
 * if you use ck_tile kernel, or similiar to this style (structure with "static __device__ operator()(...){}")
 * you can pass your kernel to ck_tile::make_kernel(), which will create a anonymous functor for you,
 * then pass it to ck_tile::launch_kernel()
 * 
 * e.g.
 *  ck_tile::launch_kernel(s,
 *                      ck_tile::make_kernel<T0, B0>(kernel_0{}, grids0, blocks0, 0, kargs0),
 *                      ck_tile::make_kernel<T0, B1>(kernel_1{}, grids1, blocks1, 0, kargs1),
 *                       ...);
 **/
// clang-format on
template <typename... Callables>
CK_TILE_HOST float launch_kernel(const stream_config& s, Callables... callables)
carlushuang's avatar
carlushuang committed
73
{
74
75
    // clang-format off
    if(!s.time_kernel_) {
76
        (callables(s),...); HIP_CHECK_ERROR(hipGetLastError());
77
78
79
80
        return 0;
    }
    if(s.is_gpu_timer_) {
        gpu_timer timer {};
carlushuang's avatar
carlushuang committed
81

82
        // warmup
83
        for(int i = 0; i < s.cold_niters_; i++) { (callables(s),...); } HIP_CHECK_ERROR(hipGetLastError());
carlushuang's avatar
carlushuang committed
84

85
        timer.start(s.stream_id_);
86
        for(int i = 0; i < s.nrepeat_; i++) { (callables(s),...); } HIP_CHECK_ERROR(hipGetLastError());
87
        timer.stop(s.stream_id_);
carlushuang's avatar
carlushuang committed
88

89
90
91
92
        return timer.duration() / s.nrepeat_;
    }
    else {
        cpu_timer timer {};
carlushuang's avatar
carlushuang committed
93

94
        // warmup
95
        for(int i = 0; i < s.cold_niters_; i++) { (callables(s),...); } HIP_CHECK_ERROR(hipGetLastError());
carlushuang's avatar
carlushuang committed
96

97
        timer.start(s.stream_id_);
98
        for(int i = 0; i < s.nrepeat_; i++) { (callables(s),...); } HIP_CHECK_ERROR(hipGetLastError());
99
        timer.stop(s.stream_id_);
carlushuang's avatar
carlushuang committed
100

101
        return timer.duration() / s.nrepeat_;
carlushuang's avatar
carlushuang committed
102
    }
103
    // clang-format on
carlushuang's avatar
carlushuang committed
104
105
106
}

} // namespace ck_tile