wuxing0105 commited on
Commit
cf24fef
·
verified ·
1 Parent(s): 4351c1f

Add files using upload-large-folder tool

Browse files
models/protenix/__pycache__/loss.cpython-310.pyc ADDED
Binary file (47.3 kB). View file
 
models/protenix/__pycache__/loss.cpython-311.pyc ADDED
Binary file (76.9 kB). View file
 
models/protenix/__pycache__/protenix.cpython-310.pyc ADDED
Binary file (16.3 kB). View file
 
models/protenix/config/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (240 Bytes). View file
 
models/protenix/config/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (329 Bytes). View file
 
models/protenix/config/__pycache__/config.cpython-310.pyc ADDED
Binary file (9.03 kB). View file
 
models/protenix/config/__pycache__/config.cpython-311.pyc ADDED
Binary file (13.6 kB). View file
 
models/protenix/config/__pycache__/extend_types.cpython-311.pyc ADDED
Binary file (2.69 kB). View file
 
models/protenix/layer_norm/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .layer_norm import FusedLayerNorm
models/protenix/layer_norm/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (180 Bytes). View file
 
models/protenix/layer_norm/__pycache__/layer_norm.cpython-310.pyc ADDED
Binary file (4.43 kB). View file
 
models/protenix/layer_norm/kernel/compat.h ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef TORCH_CHECK
2
+ #define TORCH_CHECK AT_CHECK
3
+ #endif
4
+
5
+ #ifdef VERSION_GE_1_3
6
+ #define DATA_PTR data_ptr
7
+ #else
8
+ #define DATA_PTR data
9
+ #endif
models/protenix/layer_norm/kernel/layer_norm_cuda.cpp ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright 2021- HPC-AI Technology Inc.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+
14
+ #include <torch/extension.h>
15
+ #include <c10/cuda/CUDAGuard.h>
16
+
17
+ #include <cassert>
18
+ #include <vector>
19
+ #include <functional>
20
+
21
+ #include "compat.h"
22
+
23
+ void compute_n1_n2(at::Tensor input, at::IntArrayRef normalized_shape, int& n1, int& n2) {
24
+ int idiff = input.ndimension() - normalized_shape.size();
25
+ n2 = 1;
26
+ for (int i = 0; i < (int)normalized_shape.size(); ++i) {
27
+ assert(input.sizes()[i + idiff] == normalized_shape[i]);
28
+ n2 *= normalized_shape[i];
29
+ }
30
+ n1 = 1;
31
+ for (int i = 0; i < idiff; ++i) {
32
+ n1 *= input.sizes()[i];
33
+ }
34
+ }
35
+
36
+ void check_args(at::Tensor input, at::IntArrayRef normalized_shape, int& n1, int& n2) {
37
+ int64_t normalized_ndim = normalized_shape.size();
38
+
39
+ if (normalized_ndim < 1) {
40
+ std::stringstream ss;
41
+ ss << "Expected normalized_shape to be at least 1-dimensional, i.e., "
42
+ << "containing at least one element, but got normalized_shape=" << normalized_shape;
43
+ throw std::runtime_error(ss.str());
44
+ }
45
+
46
+ auto input_shape = input.sizes();
47
+ auto input_ndim = input.dim();
48
+
49
+ if (input_ndim < normalized_ndim ||
50
+ !input_shape.slice(input_ndim - normalized_ndim).equals(normalized_shape)) {
51
+ std::stringstream ss;
52
+ ss << "Given normalized_shape=" << normalized_shape << ", expected input with shape [*";
53
+ for (auto size : normalized_shape) {
54
+ ss << ", " << size;
55
+ }
56
+ ss << "], but got input of size" << input_shape;
57
+ throw std::runtime_error(ss.str());
58
+ }
59
+
60
+ compute_n1_n2(input, normalized_shape, n1, n2);
61
+ }
62
+
63
+ void cuda_layer_norm(at::Tensor* output, at::Tensor* mean, at::Tensor* invvar, at::Tensor* input,
64
+ int n1, int n2, at::IntArrayRef normalized_shape, at::Tensor* gamma,
65
+ at::Tensor* beta, double epsilon);
66
+
67
+ #define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x " must be a CUDA tensor")
68
+ #define CHECK_CONTIGUOUS(x) TORCH_CHECK(x.is_contiguous(), #x " must be contiguous")
69
+ #define CHECK_INPUT(x) \
70
+ CHECK_CUDA(x); \
71
+ CHECK_CONTIGUOUS(x)
72
+
73
+ std::vector<at::Tensor> layer_norm_affine(at::Tensor input, at::IntArrayRef normalized_shape,
74
+ at::Tensor *gamma, at::Tensor *beta, double epsilon) {
75
+ CHECK_INPUT(input);
76
+ // CHECK_INPUT((*gamma));
77
+ // CHECK_INPUT((*beta));
78
+ int n1, n2;
79
+ check_args(input, normalized_shape, n1, n2);
80
+
81
+ const at::cuda::OptionalCUDAGuard device_guard(device_of(input));
82
+
83
+ at::Tensor output = at::empty_like(input, input.options().dtype(input.scalar_type()));
84
+ at::Tensor mean = at::empty({n1}, input.options().dtype(at::ScalarType::Float));
85
+ at::Tensor invvar = at::empty_like(mean);
86
+
87
+ cuda_layer_norm(&output, &mean, &invvar, &input, n1, n2, normalized_shape, gamma, beta, epsilon);
88
+
89
+ return {output, mean, invvar};
90
+ }
91
+
92
+ void cuda_layer_norm_gradient(at::Tensor* dout, at::Tensor* mean, at::Tensor* invvar,
93
+ at::Tensor* input, int n1, int n2, at::IntArrayRef normalized_shape,
94
+ at::Tensor* gamma, at::Tensor* beta, double epsilon,
95
+ at::Tensor* grad_input, at::Tensor* grad_gamma,
96
+ at::Tensor* grad_beta);
97
+
98
+ std::vector<at::Tensor> layer_norm_gradient_affine(at::Tensor dout, at::Tensor mean,
99
+ at::Tensor invvar, at::Tensor input,
100
+ at::IntArrayRef normalized_shape,
101
+ at::Tensor* gamma, at::Tensor* beta,
102
+ double epsilon) {
103
+ CHECK_INPUT(dout);
104
+ CHECK_INPUT(mean);
105
+ CHECK_INPUT(invvar);
106
+ CHECK_INPUT(input);
107
+ int n1, n2;
108
+ check_args(input, normalized_shape, n1, n2);
109
+
110
+ const at::cuda::OptionalCUDAGuard device_guard(device_of(input));
111
+
112
+ at::Tensor grad_input = at::empty_like(input);
113
+
114
+ at::Tensor grad_gamma;
115
+ at::Tensor grad_beta;
116
+ if (gamma != NULL)
117
+ grad_gamma = at::empty_like(*gamma);
118
+ if (beta != NULL)
119
+ grad_beta = at::empty_like(*beta);
120
+
121
+ if (gamma != NULL) {
122
+ if(beta != NULL) {
123
+ cuda_layer_norm_gradient(&dout, &mean, &invvar, &input, n1, n2, normalized_shape, gamma, beta,
124
+ epsilon, &grad_input, &grad_gamma, &grad_beta);
125
+ } else {
126
+ cuda_layer_norm_gradient(&dout, &mean, &invvar, &input, n1, n2, normalized_shape, gamma, beta,
127
+ epsilon, &grad_input, &grad_gamma, NULL);
128
+ }
129
+ } else {
130
+ if(beta != NULL) {
131
+ cuda_layer_norm_gradient(&dout, &mean, &invvar, &input, n1, n2, normalized_shape, gamma, beta,
132
+ epsilon, &grad_input, NULL, &grad_beta);
133
+ } else {
134
+ cuda_layer_norm_gradient(&dout, &mean, &invvar, &input, n1, n2, normalized_shape, gamma, beta,
135
+ epsilon, &grad_input, NULL, NULL);
136
+ }
137
+ }
138
+ return {grad_input, grad_gamma, grad_beta};
139
+ }
140
+
141
+
142
+ PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
143
+ m.def("forward_none_affine", [](at::Tensor input, at::IntArrayRef normalized_shape, double epsilon) {
144
+ return layer_norm_affine(input, normalized_shape, NULL, NULL, epsilon);
145
+ }, "LayerNorm forward (CUDA)");
146
+
147
+ m.def("forward_with_bias_affine", [](at::Tensor input, at::IntArrayRef normalized_shape, at::Tensor *beta, double epsilon) {
148
+ return layer_norm_affine(input, normalized_shape, NULL, beta, epsilon);
149
+ }, "LayerNorm forward (CUDA)");
150
+
151
+ m.def("forward_with_weight_affine", [](at::Tensor input, at::IntArrayRef normalized_shape, at::Tensor *gamma, double epsilon) {
152
+ return layer_norm_affine(input, normalized_shape, gamma, NULL, epsilon);
153
+ }, "LayerNorm forward (CUDA)");
154
+
155
+ m.def("forward_with_both_affine", [](at::Tensor input, at::IntArrayRef normalized_shape, at::Tensor *gamma, at::Tensor *beta, double epsilon) {
156
+ return layer_norm_affine(input, normalized_shape, gamma, beta, epsilon);
157
+ }, "LayerNorm forward (CUDA)");
158
+
159
+ m.def("backward_none_affine", [](at::Tensor dout, at::Tensor mean, at::Tensor invvar, at::Tensor input,
160
+ at::IntArrayRef normalized_shape, double epsilon) {
161
+ return layer_norm_gradient_affine(dout, mean, invvar, input, normalized_shape, NULL, NULL, epsilon);
162
+
163
+ }, "LayerNorm backward (CUDA)");
164
+
165
+ m.def("backward_with_bias_affine", [](at::Tensor dout, at::Tensor mean, at::Tensor invvar, at::Tensor input,
166
+ at::IntArrayRef normalized_shape, at::Tensor *beta, double epsilon) {
167
+ return layer_norm_gradient_affine(dout, mean, invvar, input, normalized_shape, NULL, beta, epsilon);
168
+ }, "LayerNorm backward (CUDA)");
169
+
170
+ m.def("backward_with_weight_affine", [](at::Tensor dout, at::Tensor mean, at::Tensor invvar, at::Tensor input,
171
+ at::IntArrayRef normalized_shape, at::Tensor *gamma, double epsilon) {
172
+ return layer_norm_gradient_affine(dout, mean, invvar, input, normalized_shape, gamma, NULL, epsilon);
173
+ }, "LayerNorm backward (CUDA)");
174
+
175
+ m.def("backward_with_both_affine", [](at::Tensor dout, at::Tensor mean, at::Tensor invvar, at::Tensor input,
176
+ at::IntArrayRef normalized_shape, at::Tensor *gamma, at::Tensor *beta, double epsilon) {
177
+ return layer_norm_gradient_affine(dout, mean, invvar, input, normalized_shape, gamma, beta, epsilon);
178
+ }, "LayerNorm backward (CUDA)");
179
+ }
models/protenix/layer_norm/kernel/layer_norm_cuda_kernel.cu ADDED
@@ -0,0 +1,599 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <cooperative_groups.h>
2
+ #include <cuda.h>
3
+ #include <cuda_runtime.h>
4
+ #include <torch/extension.h>
5
+ #include <iostream>
6
+
7
+ #include <THC/THCDeviceUtils.cuh>
8
+
9
+ #include "ATen/ATen.h"
10
+ #include "ATen/AccumulateType.h"
11
+ #include "ATen/cuda/CUDAContext.h"
12
+ #include "compat.h"
13
+ #include "type_shim.h"
14
+
15
+ #define CHECK_CUDA(x) TORCH_CHECK(x.is_cuda(), #x " must be a CUDA tensor")
16
+ #define CHECK_CONTIGUOUS(x) TORCH_CHECK(x.is_contiguous(), #x " must be contiguous")
17
+ #define CHECK_INPUT(x) \
18
+ CHECK_CUDA(x); \
19
+ CHECK_CONTIGUOUS(x)
20
+
21
+ #define WarpNum 8
22
+ #define WarpSize 32
23
+ #define BlockSzie WarpNum*WarpSize
24
+
25
+ inline __device__ void WelfordOnline(float val, float* mean, float* m2, float* count) {
26
+ *count += 1;
27
+ float delta1 = val - *mean;
28
+ *mean += delta1 / (*count);
29
+ float delta2 = val - *mean;
30
+ *m2 += delta1 * delta2;
31
+ }
32
+
33
+ inline __device__ void WelfordOnline(float b_mean, float b_m2, float b_count, float* mean,
34
+ float* m2, float* count) {
35
+ if (b_count == 0) {
36
+ return;
37
+ }
38
+ float new_count = *count + b_count;
39
+ float nb_n = b_count / new_count;
40
+ float delta = b_mean - *mean;
41
+ *mean += delta * nb_n;
42
+ *m2 += b_m2 + delta * delta * (*count) * nb_n;
43
+ *count = new_count;
44
+ }
45
+
46
+ __inline__ __device__ void WelfordWarpAllReduce(float thread_mean, float thread_m2,
47
+ float thread_count, float* mean, float* m2,
48
+ float* count) {
49
+ *mean = thread_mean;
50
+ *m2 = thread_m2;
51
+ *count = thread_count;
52
+ for (int mask = 1; mask < 32; mask *= 2) {
53
+ float b_mean = __shfl_down_sync(0xffffffff, *mean, mask);
54
+ float b_m2 = __shfl_down_sync(0xffffffff, *m2, mask);
55
+ float b_count = __shfl_down_sync(0xffffffff, *count, mask);
56
+ WelfordOnline(b_mean, b_m2, b_count, mean, m2, count);
57
+ }
58
+
59
+ *mean = __shfl_sync(0xffffffff, *mean, 0, 32);
60
+ *m2 = __shfl_sync(0xffffffff, *m2, 0, 32);
61
+ *count = __shfl_sync(0xffffffff, *count, 0, 32);
62
+ }
63
+
64
+ extern __shared__ float shared_data[];
65
+ template <typename T>
66
+ __global__ void LayerNormForward(T* input, T* output, T* gamma, T* beta, float* mean,
67
+ float* invvar, int rows, int cols, double epsilon) {
68
+ int warp_id = threadIdx.x / WarpSize;
69
+ int lane_id = threadIdx.x % WarpSize;
70
+ int row_offset = blockIdx.x * WarpNum + warp_id;
71
+
72
+ T* shared_data_warp = (T*)shared_data + warp_id*cols;
73
+
74
+ if (row_offset < rows) {
75
+ T* row_input = input + (long long)(row_offset) * (long long)(cols); // Starting point for input data
76
+ T* row_output = output + (long long)(row_offset) * (long long)(cols); // Starting point for output data
77
+
78
+ float thread_mean = 0.f;
79
+ float thread_m2 = 0.f;
80
+ float thread_count = 0.f;
81
+
82
+ float warp_mean;
83
+ float warp_m2;
84
+ float warp_count;
85
+ // load data to shared memory
86
+ #pragma unroll
87
+ for(int idx = lane_id; idx < cols; idx += WarpSize) {
88
+ shared_data_warp[idx] = row_input[idx];
89
+ WelfordOnline(static_cast<float>(shared_data_warp[idx]), &thread_mean, &thread_m2, &thread_count);
90
+ }
91
+
92
+ WelfordWarpAllReduce(thread_mean, thread_m2, thread_count, &warp_mean, &warp_m2,
93
+ &warp_count);
94
+
95
+ float row_mean = warp_mean;
96
+ float row_variance = max(warp_m2 / warp_count, 0.f);
97
+ float row_inv_var = rsqrt(row_variance + epsilon);
98
+ if (lane_id == 0) {
99
+ mean[row_offset] = row_mean;
100
+ invvar[row_offset] = row_inv_var;
101
+ }
102
+ int process_type = (gamma != NULL)*2 + (beta != NULL);
103
+ if (process_type == 0) {
104
+ #pragma unroll
105
+ for(int idx = lane_id; idx < cols; idx += WarpSize)
106
+ row_output[idx] = static_cast<T>((static_cast<float>(shared_data_warp[idx]) - row_mean) * row_inv_var);
107
+ } else if (process_type == 1) {
108
+ #pragma unroll
109
+ for(int idx = lane_id; idx < cols; idx += WarpSize)
110
+ row_output[idx] = static_cast<T>((static_cast<float>(shared_data_warp[idx]) - row_mean) * row_inv_var + beta[idx]);
111
+ } else if(process_type == 2) {
112
+ #pragma unroll
113
+ for(int idx = lane_id; idx < cols; idx += WarpSize)
114
+ row_output[idx] = static_cast<T>((static_cast<float>(shared_data_warp[idx]) - row_mean) * row_inv_var * gamma[idx]);
115
+ } else {
116
+ #pragma unroll
117
+ for(int idx = lane_id; idx < cols; idx += WarpSize)
118
+ row_output[idx] = static_cast<T>((static_cast<float>(shared_data_warp[idx]) - row_mean) * row_inv_var * gamma[idx] + beta[idx]);
119
+ }
120
+ }
121
+ }
122
+
123
+ void cuda_layer_norm(at::Tensor* output, at::Tensor* mean, at::Tensor* invvar, at::Tensor* input,
124
+ int rows, int cols, at::IntArrayRef normalized_shape, at::Tensor* gamma,
125
+ at::Tensor* beta, double epsilon) {
126
+ int grid = (rows + WarpNum - 1) / WarpNum; // each warp process one line
127
+ dim3 block(BlockSzie);
128
+ // add shared memory size
129
+ if (output->dtype() == torch::kFloat32) {
130
+ int shared_meory_size = WarpNum*sizeof(float)*cols;
131
+ LayerNormForward<float><<<grid, block, shared_meory_size>>>(
132
+ (float*)input->data_ptr(), (float*)output->data_ptr(),
133
+ gamma != NULL ? (float*)gamma->data_ptr() : NULL, beta != NULL ? (float*)beta->data_ptr() : NULL,
134
+ (float*)mean->data_ptr(), (float*)invvar->data_ptr(), rows, cols, epsilon);
135
+ } else if (output->dtype() == torch::kFloat16) {
136
+ int shared_meory_size = WarpNum*sizeof(at::Half)*cols;
137
+ LayerNormForward<at::Half><<<grid, block, shared_meory_size>>>(
138
+ (at::Half*)input->data_ptr(), (at::Half*)output->data_ptr(),
139
+ gamma != NULL ? (at::Half*)gamma->data_ptr() : NULL, beta != NULL ? (at::Half*)beta->data_ptr() : NULL,
140
+ (float*)mean->data_ptr(), (float*)invvar->data_ptr(), rows, cols, epsilon);
141
+ } else if (output->dtype() == torch::kBFloat16) {
142
+ int shared_meory_size = WarpNum*sizeof(at::BFloat16)*cols;
143
+ LayerNormForward<at::BFloat16><<<grid, block, shared_meory_size>>>(
144
+ (at::BFloat16*)input->data_ptr(), (at::BFloat16*)output->data_ptr(),
145
+ gamma != NULL ? (at::BFloat16*)gamma->data_ptr() : NULL, beta != NULL ? (at::BFloat16*)beta->data_ptr() : NULL,
146
+ (float*)mean->data_ptr(), (float*)invvar->data_ptr(), rows, cols, epsilon);
147
+ }
148
+ }
149
+
150
+ template <typename T>
151
+ struct SharedMemory;
152
+
153
+ template <>
154
+ struct SharedMemory<float> {
155
+ __device__ float* getPointer() {
156
+ extern __shared__ float s_float[];
157
+ return s_float;
158
+ }
159
+ };
160
+
161
+ template<typename T>
162
+ __inline__ __device__ T WarpReduce(T val) {
163
+ for (int mask = 16; mask > 0; mask /= 2) { val += __shfl_xor_sync(0xffffffff, val, mask); }
164
+ return val;
165
+ }
166
+
167
+ constexpr int tile_size = 32;
168
+ constexpr int num_per_block = 4;
169
+ constexpr int block_dim_x = 32;
170
+ constexpr int block_dim_y = 32 / num_per_block;
171
+
172
+ template <typename T, typename V>
173
+ __global__ void LayerNormParamGradStep1(int rows, int cols, const V* __restrict__ dy,
174
+ const T* __restrict__ x, const float* __restrict__ mean,
175
+ const float* __restrict__ inv_var,
176
+ float* __restrict__ tmp_gamma_diff, float* __restrict__ tmp_beta_diff) {
177
+ __shared__ float dgamma[32][33];
178
+ __shared__ float dbeta[32][33];
179
+ float dgamma_sum[num_per_block];
180
+ float dbeta_sum[num_per_block];
181
+ #pragma unroll
182
+ for (int index = 0; index < num_per_block; ++index) {
183
+ dgamma_sum[index] = 0;
184
+ dbeta_sum[index] = 0;
185
+ }
186
+ const int col_id = blockIdx.x * blockDim.x + threadIdx.x;
187
+ if (col_id < cols) {
188
+ for (int i = blockIdx.y * tile_size + threadIdx.y; i < rows; i += tile_size * gridDim.y) {
189
+ #pragma unroll
190
+ for (int index = 0; index < num_per_block; ++index) {
191
+ int row_id = i + index * blockDim.y;
192
+ if (row_id < rows) {
193
+ int offset = row_id * cols + col_id;
194
+ const float dy_val = static_cast<float>(dy[offset]);
195
+ const float x_val = static_cast<float>(x[offset]);
196
+ const float mean_val = mean[row_id];
197
+ const float inv_var_val = inv_var[row_id];
198
+ dgamma_sum[index] += dy_val * (x_val - mean_val) * inv_var_val;
199
+ dbeta_sum[index] += dy_val;
200
+ }
201
+ }
202
+ }
203
+ }
204
+ #pragma unroll
205
+ for (int index = 0; index < num_per_block; ++index) {
206
+ dgamma[index * blockDim.y + threadIdx.y][threadIdx.x] = dgamma_sum[index];
207
+ dbeta[index * blockDim.y + threadIdx.y][threadIdx.x] = dbeta_sum[index];
208
+ }
209
+ __syncthreads();
210
+ #pragma unroll
211
+ for (int index = 0; index < num_per_block; ++index) {
212
+ const int col_id = blockIdx.x * blockDim.x + threadIdx.y + index * blockDim.y;
213
+ if (col_id < cols) {
214
+ float gamma_sum = dgamma[threadIdx.x][threadIdx.y + index * blockDim.y];
215
+ float beta_sum = dbeta[threadIdx.x][threadIdx.y + index * blockDim.y];
216
+ float global_dgamma = WarpReduce<float>(gamma_sum);
217
+ float global_dbeta = WarpReduce<float>(beta_sum);
218
+ if (threadIdx.x == 0) {
219
+ const int offset = blockIdx.y * cols + col_id;
220
+ tmp_gamma_diff[offset] = global_dgamma;
221
+ tmp_beta_diff[offset] = global_dbeta;
222
+ }
223
+ }
224
+ }
225
+ }
226
+
227
+ template <typename T, typename V>
228
+ __global__ void LayerNormGammaGradStep1(int rows, int cols, const V* __restrict__ dy,
229
+ const T* __restrict__ x, const float* __restrict__ mean,
230
+ const float* __restrict__ inv_var, float* __restrict__ tmp_gamma_diff) {
231
+ __shared__ float dgamma[32][33];
232
+ float dgamma_sum[num_per_block];
233
+ #pragma unroll
234
+ for (int index = 0; index < num_per_block; ++index) {
235
+ dgamma_sum[index] = 0;
236
+ }
237
+ const int col_id = blockIdx.x * blockDim.x + threadIdx.x;
238
+ if (col_id < cols) {
239
+ for (int i = blockIdx.y * tile_size + threadIdx.y; i < rows; i += tile_size * gridDim.y) {
240
+ #pragma unroll
241
+ for (int index = 0; index < num_per_block; ++index) {
242
+ int row_id = i + index * blockDim.y;
243
+ if (row_id < rows) {
244
+ int offset = row_id * cols + col_id;
245
+ const float dy_val = static_cast<float>(dy[offset]);
246
+ const float x_val = static_cast<float>(x[offset]);
247
+ const float mean_val = mean[row_id];
248
+ const float inv_var_val = inv_var[row_id];
249
+ dgamma_sum[index] += dy_val * (x_val - mean_val) * inv_var_val;
250
+ }
251
+ }
252
+ }
253
+ }
254
+ #pragma unroll
255
+ for (int index = 0; index < num_per_block; ++index) {
256
+ dgamma[index * blockDim.y + threadIdx.y][threadIdx.x] = dgamma_sum[index];
257
+ }
258
+ __syncthreads();
259
+ #pragma unroll
260
+ for (int index = 0; index < num_per_block; ++index) {
261
+ const int col_id = blockIdx.x * blockDim.x + threadIdx.y + index * blockDim.y;
262
+ if (col_id < cols) {
263
+ float gamma_sum = dgamma[threadIdx.x][threadIdx.y + index * blockDim.y];
264
+ float global_dgamma = WarpReduce<float>(gamma_sum);
265
+ if (threadIdx.x == 0) {
266
+ const int offset = blockIdx.y * cols + col_id;
267
+ tmp_gamma_diff[offset] = global_dgamma;
268
+ }
269
+ }
270
+ }
271
+ }
272
+
273
+ template <typename T, typename V>
274
+ __global__ void LayerNormBetaGradStep1(int rows, int cols, const V* __restrict__ dy,
275
+ const T* __restrict__ x, const float* __restrict__ mean,
276
+ const float* __restrict__ inv_var, float* __restrict__ tmp_beta_diff) {
277
+ __shared__ float dbeta[32][33];
278
+ float dbeta_sum[num_per_block];
279
+ #pragma unroll
280
+ for (int index = 0; index < num_per_block; ++index) {
281
+ dbeta_sum[index] = 0;
282
+ }
283
+ const int col_id = blockIdx.x * blockDim.x + threadIdx.x;
284
+ if (col_id < cols) {
285
+ for (int i = blockIdx.y * tile_size + threadIdx.y; i < rows; i += tile_size * gridDim.y) {
286
+ #pragma unroll
287
+ for (int index = 0; index < num_per_block; ++index) {
288
+ int row_id = i + index * blockDim.y;
289
+ if (row_id < rows) {
290
+ int offset = row_id * cols + col_id;
291
+ const float dy_val = static_cast<float>(dy[offset]);
292
+ dbeta_sum[index] += dy_val;
293
+ }
294
+ }
295
+ }
296
+ }
297
+ #pragma unroll
298
+ for (int index = 0; index < num_per_block; ++index) {
299
+ dbeta[index * blockDim.y + threadIdx.y][threadIdx.x] = dbeta_sum[index];
300
+ }
301
+ __syncthreads();
302
+ #pragma unroll
303
+ for (int index = 0; index < num_per_block; ++index) {
304
+ const int col_id = blockIdx.x * blockDim.x + threadIdx.y + index * blockDim.y;
305
+ if (col_id < cols) {
306
+ float beta_sum = dbeta[threadIdx.x][threadIdx.y + index * blockDim.y];
307
+ float global_dbeta = WarpReduce<float>(beta_sum);
308
+ if (threadIdx.x == 0) {
309
+ const int offset = blockIdx.y * cols + col_id;
310
+ tmp_beta_diff[offset] = global_dbeta;
311
+ }
312
+ }
313
+ }
314
+ }
315
+
316
+ template <typename V>
317
+ __global__ void LayerNormParamGradStep2(const float* part_grad_gamma, const float* part_grad_beta,
318
+ const int part_size, const int n1, const int n2,
319
+ V* grad_gamma, V* grad_beta) {
320
+ // sum partial gradients for gamma and beta
321
+ SharedMemory<float> shared;
322
+ float* buf = shared.getPointer();
323
+ int i2 = blockIdx.x * blockDim.x + threadIdx.x;
324
+ if (i2 < n2) {
325
+ // each warp does sequential reductions until reduced part_size is num_warps
326
+ // int num_warp_reductions = part_size / blockDim.y;
327
+ float sum_gamma = float(0);
328
+ float sum_beta = float(0);
329
+ const float* part_grad_gamma_ptr = part_grad_gamma + i2;
330
+ const float* part_grad_beta_ptr = part_grad_beta + i2;
331
+ for (int row_idx = threadIdx.y; row_idx < part_size; row_idx += blockDim.y) {
332
+ sum_gamma += part_grad_gamma_ptr[row_idx * n2];
333
+ sum_beta += part_grad_beta_ptr[row_idx * n2];
334
+ }
335
+ // inter-warp reductions
336
+ const int nbsize3 = blockDim.x * blockDim.y / 2;
337
+ for (int offset = blockDim.y / 2; offset >= 1; offset /= 2) {
338
+ // top half write to shared memory
339
+ if (threadIdx.y >= offset && threadIdx.y < 2 * offset) {
340
+ const int write_idx = (threadIdx.y - offset) * blockDim.x + threadIdx.x;
341
+ buf[write_idx] = sum_gamma;
342
+ buf[write_idx + nbsize3] = sum_beta;
343
+ }
344
+ __syncthreads();
345
+ // bottom half sums
346
+ if (threadIdx.y < offset) {
347
+ const int read_idx = threadIdx.y * blockDim.x + threadIdx.x;
348
+ sum_gamma += buf[read_idx];
349
+ sum_beta += buf[read_idx + nbsize3];
350
+ }
351
+ __syncthreads();
352
+ }
353
+ // write out fully summed gradients
354
+ if (threadIdx.y == 0) {
355
+ grad_gamma[i2] = sum_gamma;
356
+ grad_beta[i2] = sum_beta;
357
+ }
358
+ }
359
+ }
360
+
361
+ template <typename V>
362
+ __global__ void LayerNormGammaGradStep2(const float* part_grad_gamma, const int part_size, const int n1, const int n2, V* grad_gamma) {
363
+ // sum partial gradients for gamma and beta
364
+ SharedMemory<float> shared;
365
+ float* buf = shared.getPointer();
366
+ int i2 = blockIdx.x * blockDim.x + threadIdx.x;
367
+ if (i2 < n2) {
368
+ // each warp does sequential reductions until reduced part_size is num_warps
369
+ // int num_warp_reductions = part_size / blockDim.y;
370
+ float sum_gamma = float(0);
371
+ const float* part_grad_gamma_ptr = part_grad_gamma + i2;
372
+ for (int row_idx = threadIdx.y; row_idx < part_size; row_idx += blockDim.y) {
373
+ sum_gamma += part_grad_gamma_ptr[row_idx * n2];
374
+ }
375
+ // inter-warp reductions
376
+ for (int offset = blockDim.y / 2; offset >= 1; offset /= 2) {
377
+ // top half write to shared memory
378
+ if (threadIdx.y >= offset && threadIdx.y < 2 * offset) {
379
+ const int write_idx = (threadIdx.y - offset) * blockDim.x + threadIdx.x;
380
+ buf[write_idx] = sum_gamma;
381
+ }
382
+ __syncthreads();
383
+ // bottom half sums
384
+ if (threadIdx.y < offset) {
385
+ const int read_idx = threadIdx.y * blockDim.x + threadIdx.x;
386
+ sum_gamma += buf[read_idx];
387
+ }
388
+ __syncthreads();
389
+ }
390
+ // write out fully summed gradients
391
+ if (threadIdx.y == 0) {
392
+ grad_gamma[i2] = sum_gamma;
393
+ }
394
+ }
395
+ }
396
+
397
+ template <typename V>
398
+ __global__ void LayerNormBetaGradStep2(const float* part_grad_beta, const int part_size, const int n1, const int n2, V* grad_beta) {
399
+ // sum partial gradients for gamma and beta
400
+ SharedMemory<float> shared;
401
+ float* buf = shared.getPointer();
402
+ int i2 = blockIdx.x * blockDim.x + threadIdx.x;
403
+ if (i2 < n2) {
404
+ // each warp does sequential reductions until reduced part_size is num_warps
405
+ // int num_warp_reductions = part_size / blockDim.y;
406
+ float sum_beta = float(0);
407
+ const float* part_grad_beta_ptr = part_grad_beta + i2;
408
+ for (int row_idx = threadIdx.y; row_idx < part_size; row_idx += blockDim.y) {
409
+ sum_beta += part_grad_beta_ptr[row_idx * n2];
410
+ }
411
+ // inter-warp reductions
412
+ for (int offset = blockDim.y / 2; offset >= 1; offset /= 2) {
413
+ // top half write to shared memory
414
+ if (threadIdx.y >= offset && threadIdx.y < 2 * offset) {
415
+ const int write_idx = (threadIdx.y - offset) * blockDim.x + threadIdx.x;
416
+ buf[write_idx] = sum_beta;
417
+ }
418
+ __syncthreads();
419
+ // bottom half sums
420
+ if (threadIdx.y < offset) {
421
+ const int read_idx = threadIdx.y * blockDim.x + threadIdx.x;
422
+ sum_beta += buf[read_idx];
423
+ }
424
+ __syncthreads();
425
+ }
426
+ // write out fully summed gradients
427
+ if (threadIdx.y == 0) {
428
+ grad_beta[i2] = sum_beta;
429
+ }
430
+ }
431
+ }
432
+
433
+ template <typename T, typename V>
434
+ __global__ void LayerNormInputGrad(const V* __restrict__ dout, const T* __restrict__ input,
435
+ const int rows, const int cols, const float* __restrict__ mean,
436
+ const float* __restrict__ invvar, float epsilon, const V* gamma,
437
+ T* grad_input) {
438
+ int WarpPerBlock = blockDim.x / WarpSize;
439
+ int thread_idx = threadIdx.x;
440
+ int warp_idx = thread_idx / WarpSize;
441
+ int lane_idx = thread_idx % WarpSize;
442
+
443
+ float* shared_dout = shared_data + warp_idx*cols;
444
+ float* shared_input = shared_data + WarpPerBlock*cols + warp_idx*cols;
445
+ float* shared_gamma = shared_data + 2*WarpPerBlock*cols;
446
+ int row_stride = gridDim.x*WarpPerBlock;
447
+ for(int row = blockIdx.x*WarpPerBlock+warp_idx; row < rows; row += row_stride) {
448
+ float mean_r = mean[row];
449
+ float invvar_r = invvar[row];
450
+ // load dout, input and gamma
451
+ long long data_offset = (long long)(row) * cols;
452
+ const V* dout_r = dout + data_offset;
453
+ const T* input_r = input + data_offset;
454
+ T* grad_input_r = grad_input + data_offset;
455
+ #pragma unroll
456
+ for(int col = lane_idx; col < cols; col += WarpSize) {
457
+ shared_dout[col] = float(dout_r[col]);
458
+ shared_input[col] = float(input_r[col]);
459
+ }
460
+ if(warp_idx == 0) {
461
+ #pragma unroll
462
+ for(int col = lane_idx; col < cols; col += WarpSize) {
463
+ shared_gamma[col] = gamma != NULL ? float(gamma[col]) : 1.0f;
464
+ }
465
+ }
466
+ __syncthreads();
467
+
468
+ float gamma_dout = 0.0;
469
+ float gamma_dout_input_mean = 0.0;
470
+ // reduction, gamma*dout and gamma*dout*(input-mean)
471
+ #pragma unroll
472
+ for(int col = lane_idx; col < cols; col += WarpSize) {
473
+ float temp = shared_gamma[col] * shared_dout[col];
474
+ gamma_dout += temp;
475
+ gamma_dout_input_mean += temp * (shared_input[col] - mean_r);
476
+ }
477
+ float global_gamma_dout = WarpReduce<float>(gamma_dout);
478
+ float global_gamma_dout_input_mean = WarpReduce<float>(gamma_dout_input_mean);
479
+
480
+ float part3_temp_value = global_gamma_dout_input_mean * invvar_r * invvar_r * invvar_r / cols;
481
+ float part2 = global_gamma_dout * invvar_r / cols;
482
+ #pragma unroll
483
+ for(int col = lane_idx; col < cols; col += WarpSize) {
484
+ float part1 = shared_gamma[col] * shared_dout[col] * invvar_r;
485
+ float part3 = (shared_input[col] - mean_r) * part3_temp_value;
486
+ grad_input_r[col] = part1 - part2 - part3;
487
+ }
488
+ }
489
+ }
490
+
491
+ template <typename T, typename V>
492
+ int GetGirdDimY(const int64_t num_instances, const int64_t norm_size) {
493
+ const int grid_dim_x = (norm_size + tile_size - 1) / tile_size;
494
+ const int max_grid_dim_y = (num_instances + tile_size - 1) / tile_size;
495
+ const int block_size = block_dim_x * block_dim_y;
496
+ int max_active_blocks = 0;
497
+ cudaOccupancyMaxActiveBlocksPerMultiprocessor(
498
+ &max_active_blocks, LayerNormParamGradStep1<T, V>, block_size, 0);
499
+ int waves = 1;
500
+ int dev;
501
+ cudaGetDevice(&dev);
502
+ int sm_count;
503
+ cudaDeviceGetAttribute(&sm_count, cudaDevAttrMultiProcessorCount, dev);
504
+ int num_blocks = max_active_blocks * sm_count * waves;
505
+ int grid_dim_y = std::min(max_grid_dim_y, static_cast<int>(num_blocks / grid_dim_x));
506
+ return std::max(grid_dim_y, 1);
507
+ }
508
+
509
+ template <typename T, typename V>
510
+ void HostLayerNormGradient(const V* dout, const float* mean, const float* invvar, at::Tensor* input, int n1,
511
+ int n2, const V* gamma, const V* beta, double epsilon, T* grad_input,
512
+ V* grad_gamma, V* grad_beta) {
513
+ auto stream = at::cuda::getCurrentCUDAStream().stream();
514
+
515
+ if (gamma != NULL && beta != NULL) {
516
+ // compute grad_gamma(j) and grad_beta(j)
517
+ const int part_size = GetGirdDimY<T, V>(n1, n2);
518
+ const int grid_dim_x = (n2 + tile_size - 1) / tile_size;
519
+ const int grid_dim_y = part_size;
520
+
521
+ at::Tensor part_grad_gamma = at::empty({part_size, n2}, input->options().dtype(at::ScalarType::Float));
522
+ at::Tensor part_grad_beta = at::empty_like(part_grad_gamma);
523
+ LayerNormParamGradStep1<T, V><<<dim3(grid_dim_x, grid_dim_y), dim3(32, 32 / num_per_block)>>>(
524
+ n1, n2, dout, input->DATA_PTR<T>(), mean, invvar, part_grad_gamma.DATA_PTR<float>(), part_grad_beta.DATA_PTR<float>()
525
+ );
526
+
527
+ const dim3 threads3(32, 8, 1);
528
+ const dim3 blocks3((n2 + 32 - 1) / 32, 1, 1);
529
+ const int nshared3 = threads3.x * threads3.y * sizeof(float);
530
+ LayerNormParamGradStep2<<<blocks3, threads3, nshared3, stream>>>(
531
+ part_grad_gamma.DATA_PTR<float>(), part_grad_beta.DATA_PTR<float>(), part_size, n1, n2,
532
+ grad_gamma, grad_beta);
533
+ } else if (gamma != NULL && beta == NULL) {
534
+ // compute grad_gamma(j) and grad_beta(j)
535
+ const int part_size = GetGirdDimY<T, V>(n1, n2);
536
+ const int grid_dim_x = (n2 + tile_size - 1) / tile_size;
537
+ const int grid_dim_y = part_size;
538
+
539
+ at::Tensor part_grad_gamma = at::empty({part_size, n2}, input->options().dtype(at::ScalarType::Float));
540
+ LayerNormGammaGradStep1<T, V><<<dim3(grid_dim_x, grid_dim_y), dim3(32, 32 / num_per_block)>>>(
541
+ n1, n2, dout, input->DATA_PTR<T>(), mean, invvar, part_grad_gamma.DATA_PTR<float>());
542
+
543
+ const dim3 threads3(32, 8, 1);
544
+ const dim3 blocks3((n2 + 32 - 1) / 32, 1, 1);
545
+ const int nshared3 = threads3.x * threads3.y * sizeof(float);
546
+ LayerNormGammaGradStep2<<<blocks3, threads3, nshared3, stream>>>(
547
+ part_grad_gamma.DATA_PTR<float>(), part_size, n1, n2, grad_gamma);
548
+ } else if (gamma == NULL && beta!= NULL) {
549
+ // compute grad_gamma(j) and grad_beta(j)
550
+ const int part_size = GetGirdDimY<T, V>(n1, n2);
551
+ const int grid_dim_x = (n2 + tile_size - 1) / tile_size;
552
+ const int grid_dim_y = part_size;
553
+
554
+ at::Tensor part_grad_beta = at::empty({part_size, n2}, input->options().dtype(at::ScalarType::Float));
555
+ LayerNormBetaGradStep1<T, V><<<dim3(grid_dim_x, grid_dim_y), dim3(32, 32 / num_per_block)>>>(
556
+ n1, n2, dout, input->DATA_PTR<T>(), mean, invvar, part_grad_beta.DATA_PTR<float>()
557
+ );
558
+
559
+ const dim3 threads3(32, 8, 1);
560
+ const dim3 blocks3((n2 + 32 - 1) / 32, 1, 1);
561
+ const int nshared3 = threads3.x * threads3.y * sizeof(float);
562
+ LayerNormBetaGradStep2<<<blocks3, threads3, nshared3, stream>>>(
563
+ part_grad_beta.DATA_PTR<float>(), part_size, n1, n2, grad_beta);
564
+ }
565
+
566
+ const uint64_t maxGridY = at::cuda::getCurrentDeviceProperties()->maxGridSize[1];
567
+ #define BlockDim 128
568
+ int WarpNumPerBlock = BlockDim / WarpSize;
569
+ const dim3 threads1(BlockDim);
570
+ int nshared = sizeof(float)*n2*(WarpNumPerBlock*2 + 1);
571
+
572
+ int max_active_blocks = 0;
573
+ cudaOccupancyMaxActiveBlocksPerMultiprocessor(
574
+ &max_active_blocks, LayerNormInputGrad<T, V>, BlockDim, nshared);
575
+ int dev;
576
+ cudaGetDevice(&dev);
577
+ int sm_count;
578
+ cudaDeviceGetAttribute(&sm_count, cudaDevAttrMultiProcessorCount, dev);
579
+
580
+ const dim3 blocks1(std::min((uint64_t)((n1 + WarpNumPerBlock - 1)/WarpNumPerBlock), (uint64_t)(max_active_blocks * sm_count)));
581
+ LayerNormInputGrad<<<blocks1, threads1, nshared>>>(dout, input->DATA_PTR<T>(), n1, n2, mean, invvar, float(epsilon), gamma, grad_input);
582
+ }
583
+
584
+ void cuda_layer_norm_gradient(at::Tensor* dout, at::Tensor* mean, at::Tensor* invvar,
585
+ at::Tensor* input, int n1, int n2, at::IntArrayRef normalized_shape,
586
+ at::Tensor* gamma, at::Tensor* beta, double epsilon,
587
+ at::Tensor* grad_input, at::Tensor* grad_gamma,
588
+ at::Tensor* grad_beta) {
589
+ using namespace at;
590
+ DISPATCH_FLOAT_HALF_AND_BFLOAT_INOUT_TYPES(
591
+ input->scalar_type(), dout->scalar_type(), "cuda_layer_norm_gradient_kernel",
592
+ HostLayerNormGradient(dout->DATA_PTR<scalar_t_out>(), mean->DATA_PTR<float>(),
593
+ invvar->DATA_PTR<float>(), input, n1, n2,
594
+ gamma != NULL ? gamma->DATA_PTR<scalar_t_out>() : NULL,
595
+ beta != NULL ? beta->DATA_PTR<scalar_t_out>() : NULL, epsilon,
596
+ grad_input->DATA_PTR<scalar_t_in>(),
597
+ gamma != NULL ? grad_gamma->DATA_PTR<scalar_t_out>() : NULL,
598
+ beta != NULL ? grad_beta->DATA_PTR<scalar_t_out>() : NULL);)
599
+ }
models/protenix/layer_norm/kernel/type_shim.h ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <ATen/ATen.h>
2
+
3
+ #include "compat.h"
4
+
5
+ #define DISPATCH_HALF_AND_BFLOAT(TYPE, NAME, ...) \
6
+ switch (TYPE) { \
7
+ case at::ScalarType::Half: { \
8
+ using scalar_t = at::Half; \
9
+ __VA_ARGS__; \
10
+ break; \
11
+ } \
12
+ case at::ScalarType::BFloat16: { \
13
+ using scalar_t = at::BFloat16; \
14
+ __VA_ARGS__; \
15
+ break; \
16
+ } \
17
+ default: \
18
+ AT_ERROR(#NAME, " not implemented for '", toString(TYPE), "'"); \
19
+ }
20
+
21
+ #define DISPATCH_FLOAT_HALF_AND_BFLOAT_INOUT_TYPES(TYPEIN, TYPEOUT, NAME, ...) \
22
+ switch (TYPEIN) { \
23
+ case at::ScalarType::Float: { \
24
+ using scalar_t_in = float; \
25
+ switch (TYPEOUT) { \
26
+ case at::ScalarType::Float: { \
27
+ using scalar_t_out = float; \
28
+ __VA_ARGS__; \
29
+ break; \
30
+ } \
31
+ case at::ScalarType::Half: { \
32
+ using scalar_t_out = at::Half; \
33
+ __VA_ARGS__; \
34
+ break; \
35
+ } \
36
+ case at::ScalarType::BFloat16: { \
37
+ using scalar_t_out = at::BFloat16; \
38
+ __VA_ARGS__; \
39
+ break; \
40
+ } \
41
+ default: \
42
+ AT_ERROR(#NAME, " not implemented for '", toString(TYPEOUT), "'"); \
43
+ } \
44
+ break; \
45
+ } \
46
+ case at::ScalarType::Half: { \
47
+ using scalar_t_in = at::Half; \
48
+ using scalar_t_out = at::Half; \
49
+ __VA_ARGS__; \
50
+ break; \
51
+ } \
52
+ case at::ScalarType::BFloat16: { \
53
+ using scalar_t_in = at::BFloat16; \
54
+ using scalar_t_out = at::BFloat16; \
55
+ __VA_ARGS__; \
56
+ break; \
57
+ } \
58
+ default: \
59
+ AT_ERROR(#NAME, " not implemented for '", toString(TYPEIN), "'"); \
60
+ }
61
+
62
+ // Forward/backward compatiblity hack around
63
+ // https://github.com/pytorch/pytorch/commit/3aeb78079bcd68282fe9117088e138b77318e288
64
+ // pending more future-proof guidance from upstream.
65
+ // struct TypeShim
66
+ // {
67
+ // const at::Type& payload;
68
+ // TypeShim(const at::Type& type) : payload(type) {}
69
+ // // Enable trivial conversion to a const at::Type& for pre-3aeb78
70
+ // operator const at::Type&(){ return payload; };
71
+ // // Enable dispatch switch statements to take *this directly for post-3aeb78
72
+ // //operator at::ScalarType(){ return payload.; };
73
+ // };
74
+
75
+ #define DISPATCH_FLOAT_AND_HALF(TYPE, LEVEL, NAME, ...) \
76
+ switch (TYPE) { \
77
+ case at::ScalarType::Float: { \
78
+ using scalar_t_##LEVEL = float; \
79
+ __VA_ARGS__; \
80
+ break; \
81
+ } \
82
+ case at::ScalarType::Half: { \
83
+ using scalar_t_##LEVEL = at::Half; \
84
+ __VA_ARGS__; \
85
+ break; \
86
+ } \
87
+ default: \
88
+ AT_ERROR(#NAME, " not implemented for '", toString(TYPE), "'"); \
89
+ }
90
+
91
+ #define DISPATCH_FLOAT_HALF_AND_BYTE(TYPE, LEVEL, NAME, ...) \
92
+ switch (TYPE) { \
93
+ case at::ScalarType::Float: { \
94
+ using scalar_t_##LEVEL = float; \
95
+ __VA_ARGS__; \
96
+ break; \
97
+ } \
98
+ case at::ScalarType::Half: { \
99
+ using scalar_t_##LEVEL = at::Half; \
100
+ __VA_ARGS__; \
101
+ break; \
102
+ } \
103
+ case at::ScalarType::Byte: { \
104
+ using scalar_t_##LEVEL = uint8_t; \
105
+ __VA_ARGS__; \
106
+ break; \
107
+ } \
108
+ default: \
109
+ AT_ERROR(#NAME, " not implemented for '", toString(TYPE), "'"); \
110
+ }
111
+
112
+ #define DISPATCH_DOUBLE_FLOAT_AND_HALF(TYPE, LEVEL, NAME, ...) \
113
+ switch (TYPE) { \
114
+ case at::ScalarType::Double: { \
115
+ using scalar_t_##LEVEL = double; \
116
+ __VA_ARGS__; \
117
+ break; \
118
+ } \
119
+ case at::ScalarType::Float: { \
120
+ using scalar_t_##LEVEL = float; \
121
+ __VA_ARGS__; \
122
+ break; \
123
+ } \
124
+ case at::ScalarType::Half: { \
125
+ using scalar_t_##LEVEL = at::Half; \
126
+ __VA_ARGS__; \
127
+ break; \
128
+ } \
129
+ default: \
130
+ AT_ERROR(#NAME, " not implemented for '", toString(TYPE), "'"); \
131
+ }
132
+
133
+ #define DISPATCH_DOUBLE_AND_FLOAT(TYPE, LEVEL, NAME, ...) \
134
+ switch (TYPE) { \
135
+ case at::ScalarType::Double: { \
136
+ using scalar_t_##LEVEL = double; \
137
+ __VA_ARGS__; \
138
+ break; \
139
+ } \
140
+ case at::ScalarType::Float: { \
141
+ using scalar_t_##LEVEL = float; \
142
+ __VA_ARGS__; \
143
+ break; \
144
+ } \
145
+ default: \
146
+ AT_ERROR(#NAME, " not implemented for '", toString(TYPE), "'"); \
147
+ }
148
+
149
+ template <typename T>
150
+ __device__ __forceinline__ T
151
+ reduce_block_into_lanes(T *x, T val, int lanes = 1,
152
+ bool share_result = false) // lanes is intended to be <= 32.
153
+ {
154
+ int tid = threadIdx.x + threadIdx.y * blockDim.x;
155
+ int blockSize = blockDim.x * blockDim.y; // blockSize is intended to be a multiple of 32.
156
+
157
+ if (blockSize >= 64) {
158
+ x[tid] = val;
159
+ __syncthreads();
160
+ }
161
+
162
+ #pragma unroll
163
+ for (int i = (blockSize >> 1); i >= 64; i >>= 1) {
164
+ if (tid < i) x[tid] = x[tid] + x[tid + i];
165
+ __syncthreads();
166
+ }
167
+
168
+ T final;
169
+
170
+ if (tid < 32) {
171
+ if (blockSize >= 64)
172
+ final = x[tid] + x[tid + 32];
173
+ else
174
+ final = val;
175
+ // __SYNCWARP();
176
+
177
+ #pragma unroll
178
+ for (int i = 16; i >= lanes; i >>= 1)
179
+ final = final + __shfl_down_sync(0xffffffff, final, i);
180
+ }
181
+
182
+ if (share_result) {
183
+ if (tid < lanes) x[tid] = final; // EpilogueOp
184
+ // Make sure the smem result is visible to all warps.
185
+ __syncthreads();
186
+ }
187
+
188
+ return final;
189
+ }
190
+
191
+ template <typename T>
192
+ __device__ __forceinline__ T
193
+ reduce_block_into_lanes_max_op(T *x, T val, int lanes = 1,
194
+ bool share_result = false) // lanes is intended to be <= 32.
195
+ {
196
+ int tid = threadIdx.x + threadIdx.y * blockDim.x;
197
+ int blockSize = blockDim.x * blockDim.y; // blockSize is intended to be a multiple of 32.
198
+
199
+ if (blockSize >= 64) {
200
+ x[tid] = val;
201
+ __syncthreads();
202
+ }
203
+
204
+ #pragma unroll
205
+ for (int i = (blockSize >> 1); i >= 64; i >>= 1) {
206
+ if (tid < i) x[tid] = fmaxf(fabsf(x[tid]), fabsf(x[tid + i]));
207
+ __syncthreads();
208
+ }
209
+
210
+ T final;
211
+
212
+ if (tid < 32) {
213
+ if (blockSize >= 64)
214
+ final = fmaxf(fabsf(x[tid]), fabsf(x[tid + 32]));
215
+ else
216
+ final = val;
217
+ // __SYNCWARP();
218
+
219
+ #pragma unroll
220
+ for (int i = 16; i >= lanes; i >>= 1)
221
+ final = fmaxf(fabsf(final), fabsf(__shfl_down_sync(0xffffffff, final, i)));
222
+ }
223
+
224
+ if (share_result) {
225
+ if (tid < lanes) x[tid] = final; // EpilogueOp
226
+ // Make sure the smem result is visible to all warps.
227
+ __syncthreads();
228
+ }
229
+
230
+ return final;
231
+ }
models/protenix/layer_norm/layer_norm.py ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import importlib
2
+ import numbers
3
+ import os
4
+ import sys
5
+ import time
6
+
7
+ import torch
8
+ from torch.nn.parameter import Parameter
9
+
10
+ sys.path.append(os.path.dirname(__file__))
11
+
12
+ try:
13
+ fastfold_layer_norm_cuda = importlib.import_module("fastfold_layer_norm_cuda")
14
+ except ImportError:
15
+ from models.protenix.layer_norm.torch_ext_compile import compile
16
+
17
+ current_dir = os.path.dirname(__file__)
18
+ fastfold_layer_norm_cuda = compile(
19
+ name="fastfold_layer_norm_cuda",
20
+ sources=[
21
+ os.path.join(f"{current_dir}/kernel", file)
22
+ for file in ["layer_norm_cuda.cpp", "layer_norm_cuda_kernel.cu"]
23
+ ],
24
+ extra_include_paths=[f"{current_dir}/kernel"],
25
+ build_directory=current_dir,
26
+ )
27
+
28
+
29
+ class FusedLayerNormAffineFunction(torch.autograd.Function):
30
+
31
+ @staticmethod
32
+ def forward(ctx, input, weight, bias, normalized_shape, eps):
33
+ d = input.dtype
34
+
35
+ ctx.normalized_shape = normalized_shape
36
+ ctx.eps = eps
37
+ input_ = input.contiguous()
38
+
39
+ if weight is None:
40
+ if bias is None:
41
+ output, mean, invvar = fastfold_layer_norm_cuda.forward_none_affine(
42
+ input_, ctx.normalized_shape, ctx.eps
43
+ )
44
+ else:
45
+ output, mean, invvar = (
46
+ fastfold_layer_norm_cuda.forward_with_bias_affine(
47
+ input_, ctx.normalized_shape, bias.to(d), ctx.eps
48
+ )
49
+ )
50
+ else:
51
+ if bias is None:
52
+ output, mean, invvar = (
53
+ fastfold_layer_norm_cuda.forward_with_weight_affine(
54
+ input_, ctx.normalized_shape, weight.to(d), ctx.eps
55
+ )
56
+ )
57
+ else:
58
+ output, mean, invvar = (
59
+ fastfold_layer_norm_cuda.forward_with_both_affine(
60
+ input_, ctx.normalized_shape, weight.to(d), bias.to(d), ctx.eps
61
+ )
62
+ )
63
+ ctx.save_for_backward(input_, weight, bias, mean, invvar)
64
+ return output
65
+
66
+ @staticmethod
67
+ def backward(ctx, grad_output):
68
+ d = grad_output.dtype
69
+ input_, weight_, bias_, mean, invvar = ctx.saved_tensors
70
+ grad_input = grad_weight = grad_bias = None
71
+
72
+ if weight_ is None:
73
+ if bias_ is None:
74
+ grad_input, grad_weight, grad_bias = (
75
+ fastfold_layer_norm_cuda.backward_none_affine(
76
+ grad_output.contiguous(),
77
+ mean,
78
+ invvar,
79
+ input_,
80
+ ctx.normalized_shape,
81
+ ctx.eps,
82
+ )
83
+ )
84
+ else:
85
+ grad_input, grad_weight, grad_bias = (
86
+ fastfold_layer_norm_cuda.backward_with_bias_affine(
87
+ grad_output.contiguous(),
88
+ mean,
89
+ invvar,
90
+ input_,
91
+ ctx.normalized_shape,
92
+ bias_.to(dtype=d),
93
+ ctx.eps,
94
+ )
95
+ )
96
+ else:
97
+ if bias_ is None:
98
+ grad_input, grad_weight, grad_bias = (
99
+ fastfold_layer_norm_cuda.backward_with_weight_affine(
100
+ grad_output.contiguous(),
101
+ mean,
102
+ invvar,
103
+ input_,
104
+ ctx.normalized_shape,
105
+ weight_.to(dtype=d),
106
+ ctx.eps,
107
+ )
108
+ )
109
+ else:
110
+ grad_input, grad_weight, grad_bias = (
111
+ fastfold_layer_norm_cuda.backward_with_both_affine(
112
+ grad_output.contiguous(),
113
+ mean,
114
+ invvar,
115
+ input_,
116
+ ctx.normalized_shape,
117
+ weight_.to(dtype=d),
118
+ bias_.to(dtype=d),
119
+ ctx.eps,
120
+ )
121
+ )
122
+ return (
123
+ grad_input,
124
+ None if weight_ is None else grad_weight,
125
+ None if bias_ is None else grad_bias,
126
+ None,
127
+ None,
128
+ )
129
+
130
+
131
+ class FusedLayerNorm(torch.nn.Module):
132
+
133
+ def __init__(
134
+ self,
135
+ normalized_shape,
136
+ create_scale=True,
137
+ create_offset=True,
138
+ eps=1e-5,
139
+ ):
140
+ """
141
+ Args:
142
+ normalized_shape (int or list or torch.Size) input shape from an expected input of size
143
+ create_scale (bool) If set to False, the layer will not learn an additive weight, Default: True
144
+ create_offset (bool) If set to False, the layer will not learn an additive bias, Default: True
145
+ eps (float) a value added to the denominator for numerical stability. Default: 1e-5
146
+ """
147
+ super(FusedLayerNorm, self).__init__()
148
+
149
+ if isinstance(normalized_shape, numbers.Integral):
150
+ normalized_shape = (normalized_shape,)
151
+ self.normalized_shape = torch.Size(normalized_shape)
152
+ self.eps = eps
153
+ if create_scale:
154
+ self.weight = Parameter(torch.ones(*normalized_shape))
155
+ else:
156
+ self.weight = None
157
+
158
+ if create_offset:
159
+ self.bias = Parameter(torch.zeros(*normalized_shape))
160
+ else:
161
+ self.bias = None
162
+
163
+ self.reset_parameters()
164
+
165
+ def reset_parameters(self):
166
+ if self.weight is not None:
167
+ torch.nn.init.ones_(self.weight)
168
+ if self.bias is not None:
169
+ torch.nn.init.zeros_(self.bias)
170
+
171
+ def forward(self, input):
172
+ return FusedLayerNormAffineFunction.apply(
173
+ input, self.weight, self.bias, self.normalized_shape, self.eps
174
+ )
175
+
176
+
177
+ if __name__ == "__main__":
178
+ dtype = torch.float32
179
+ data = torch.rand(10, 10).cuda().to(dtype=dtype)
180
+ data1 = data * 1
181
+ data.requires_grad = True
182
+ data1.requires_grad = True
183
+ layer_norm = (
184
+ FusedLayerNorm(10, create_scale=True, create_offset=True).cuda().to(dtype=dtype)
185
+ )
186
+ layer_norm_torch = torch.nn.LayerNorm(10).cuda().to(dtype=dtype)
187
+ out = layer_norm(data)
188
+ out1 = layer_norm_torch(data1)
189
+ # print(out - out1)
190
+ loss = out.sum()
191
+ loss.backward()
192
+ loss1 = out1.sum()
193
+ loss1.backward()
194
+ print(data.grad - data1.grad)
195
+ print(layer_norm.weight.grad - layer_norm_torch.weight.grad)
196
+ print(layer_norm.bias.grad - layer_norm_torch.bias.grad)
197
+ print(layer_norm.weight.grad, layer_norm.bias.grad)
198
+
models/protenix/layer_norm/torch_ext_compile.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ from torch.utils.cpp_extension import load
4
+
5
+
6
+ def compile(name, sources, extra_include_paths, build_directory):
7
+ os.environ["TORCH_CUDA_ARCH_LIST"] = "7.0;8.0"
8
+ return load(
9
+ name=name,
10
+ sources=sources,
11
+ extra_include_paths=extra_include_paths,
12
+ extra_cflags=[
13
+ "-O3",
14
+ "-DVERSION_GE_1_1",
15
+ "-DVERSION_GE_1_3",
16
+ "-DVERSION_GE_1_5",
17
+ ],
18
+ extra_cuda_cflags=[
19
+ "-O3",
20
+ "--use_fast_math",
21
+ "-DVERSION_GE_1_1",
22
+ "-DVERSION_GE_1_3",
23
+ "-DVERSION_GE_1_5",
24
+ "-std=c++17",
25
+ "-maxrregcount=50",
26
+ "-U__CUDA_NO_HALF_OPERATORS__",
27
+ "-U__CUDA_NO_HALF_CONVERSIONS__",
28
+ "--expt-relaxed-constexpr",
29
+ "--expt-extended-lambda",
30
+ "-gencode",
31
+ "arch=compute_70,code=sm_70",
32
+ "-gencode",
33
+ "arch=compute_80,code=sm_80",
34
+ "-gencode",
35
+ "arch=compute_86,code=sm_86",
36
+ "-gencode",
37
+ "arch=compute_90,code=sm_90",
38
+ ],
39
+ verbose=True,
40
+ build_directory=build_directory,
41
+ )
weight/model_v0.5.0.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9ea20b0aba42f2256711da1d0cd081510a4b291e64375bff6b70ced70b87a5f1
3
+ size 1474265486