| 91 | } |
| 92 | |
| 93 | bool PreluOps::Run(Node* node) |
| 94 | { |
| 95 | // inplace implement |
| 96 | Tensor* input_tensor = node->GetInputTensor(0); |
| 97 | Tensor* output_tensor = node->GetOutputTensor(0); |
| 98 | const TShape& shape = input_tensor->GetShape(); |
| 99 | const std::vector<int> dims = shape.GetDim(); |
| 100 | int channel_size = dims[2] * dims[3]; |
| 101 | int channel_num = dims[1]; |
| 102 | int img_size = channel_size * channel_num; |
| 103 | const float* input = ( float* )get_tensor_mem(input_tensor); |
| 104 | float* output = ( float* )get_tensor_mem(output_tensor); |
| 105 | const Tensor* slope_tensor = node->GetInputTensor(1); |
| 106 | float* slope = ( float* )get_tensor_mem(slope_tensor); |
| 107 | |
| 108 | int cpu_number = cpu_info->GetCPUNumber(); |
| 109 | int block = channel_num ; |
| 110 | block = block > 0 ? block : 1; |
| 111 | int num_task = cpu_number < block ? cpu_number : block; |
| 112 | int step = channel_num / num_task; |
| 113 | |
| 114 | for(int n = 0; n < dims[0]; n++) |
| 115 | { |
| 116 | const float *input_data = input + n * img_size; |
| 117 | float *out_data = output + n * img_size; |
| 118 | |
| 119 | if(num_task == 1) |
| 120 | prelu_kernel( 0, 0, &step, input_data, out_data, slope, channel_size); |
| 121 | else |
| 122 | { |
| 123 | MULTI_THREAD_START(num_task, step, p_id, p_param) |
| 124 | prelu_kernel(0, p_id, p_param, input_data, out_data, slope, channel_size); |
| 125 | MULTI_THREAD_END(); |
| 126 | } |
| 127 | if(num_task * step != channel_num) |
| 128 | { |
| 129 | int offset = num_task * step; |
| 130 | int remain_num = channel_num - offset; |
| 131 | input_data += offset * channel_size; |
| 132 | out_data += offset * channel_size; |
| 133 | prelu_kernel(0, 0, &remain_num, input_data, out_data, slope + offset, channel_size); |
| 134 | } |
| 135 | } |
| 136 | return true; |
| 137 | } |
| 138 | |
| 139 | NodeOps* SelectFunc(const CPUInfo* cpu_info, Node* node) |
| 140 | { |
nothing calls this directly
no test coverage detected