| 115 | } // namespace |
| 116 | |
| 117 | void Softmax::eval_cpu(const std::vector<array>& inputs, array& out) { |
| 118 | assert(inputs.size() == 1); |
| 119 | |
| 120 | // Make sure that the last dimension is contiguous |
| 121 | auto set_output = [s = stream(), &out](const array& x) { |
| 122 | if (x.flags().contiguous && x.strides()[x.ndim() - 1] == 1) { |
| 123 | if (x.is_donatable()) { |
| 124 | out.copy_shared_buffer(x); |
| 125 | } else { |
| 126 | out.set_data( |
| 127 | allocator::malloc(x.data_size() * x.itemsize()), |
| 128 | x.data_size(), |
| 129 | x.strides(), |
| 130 | x.flags()); |
| 131 | } |
| 132 | return x; |
| 133 | } else { |
| 134 | array x_copy = contiguous_copy_cpu(x, s); |
| 135 | out.copy_shared_buffer(x_copy); |
| 136 | return x_copy; |
| 137 | } |
| 138 | }; |
| 139 | |
| 140 | auto in = set_output(inputs[0]); |
| 141 | |
| 142 | switch (in.dtype()) { |
| 143 | case float32: |
| 144 | softmax<float, float>(in, out, stream()); |
| 145 | break; |
| 146 | case float16: |
| 147 | if (precise_) { |
| 148 | softmax<float16_t, float>(in, out, stream()); |
| 149 | } else { |
| 150 | softmax<float16_t, float16_t>(in, out, stream()); |
| 151 | } |
| 152 | break; |
| 153 | case bfloat16: |
| 154 | if (precise_) { |
| 155 | softmax<bfloat16_t, float>(in, out, stream()); |
| 156 | } else { |
| 157 | softmax<bfloat16_t, bfloat16_t>(in, out, stream()); |
| 158 | } |
| 159 | break; |
| 160 | case float64: |
| 161 | softmax<double, double>(in, out, stream()); |
| 162 | break; |
| 163 | default: |
| 164 | throw std::runtime_error( |
| 165 | "[softmax] Only defined for floating point types."); |
| 166 | break; |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | } // namespace mlx::core |
nothing calls this directly
no test coverage detected