Halide
Halide copied to clipboard
Runtime error (ambiguous function call) for float16 on Metal backend
When using float16 and a metal backend, I'm getting runtime errors that complains calls to min/max/select are ambiguous because METAL_FUNC with both half and float signatures exist.
This error is triggered if the computation involves both half and float, even when explicit cast is used before calling the functions min/max/select.
Here is a minimum example that exposed this error for min and select. I'm using Mac M2 with target=host-metal
, and I'm building Halide from top of tree.
// f16_bug_generator.cpp
#include "Halide.h"
#include <stdio.h>
using namespace Halide;
class F16BugGenerator : public Halide::Generator<F16BugGenerator> {
public:
Input<Buffer<>> input{"input", 2};
Output<Buffer<>> output{"output", 2};
Var x, y;
void generate() {
Expr val = cast(output.type(), input(x, y) + 1.f);
Expr clamp_val = clamp(val, cast(output.type(), 0), cast(output.type(), 1));
output(x, y) = cast(output.type(), select(clamp_val > 1, cast<float>(abs(clamp_val)), cast<float>(fast_pow(clamp_val, 1.f / 2.2f))));
if (get_target().has_gpu_feature()) {
printf("GPU schedule\n");
Var xi, xo, yi, yo;
output.compute_root()
.gpu_tile(x, y, xo, yo, xi, yi, 8, 32);
}
}
};
HALIDE_REGISTER_GENERATOR(F16BugGenerator, f16_bug_generator)
// f16_bug_test.cpp
#include "HalideBuffer.h"
#include "f16_bug_generator.h"
#include <stdio.h>
#include <stdlib.h>
using half = _Float16;
int main(int argc, char **argv) {
Halide::Runtime::Buffer<half> input(32, 32);
Halide::Runtime::Buffer<half> output(32, 32);
f16_bug_generator(input, output);
printf("success\n");
return 0;
}
// f16_bug.sh
export DYLD_LIBRARY_PATH=/usr/lib:/Users/yutingyang/Documents/halide_build/distrib/lib
g++ f16_bug_generator.cpp ~/Documents/halide_build/distrib/tools/GenGen.cpp -g -std=c++17 -fno-rtti -I ~/Documents/halide_build/distrib/include -L ~/Documents/halide_build/distrib/lib -lHalide -o f16_bug_generator
./f16_bug_generator -g f16_bug_generator -o . target=host-metal input.type=float16 output.type=float16
g++ -std=c++17 -I ~/Documents/halide_build/distrib/include -L ~/Documents/halide_build/distrib/lib -ldl -lpthread -lz -framework Metal -framework Foundation f16_bug_test.cpp f16_bug_generator.a -o f16_bug_test
./f16_bug_test
Error message:
2024-05-29 14:14:11.017 f16_bug_test[57266:14995657] Error Domain=MTLLibraryErrorDomain Code=3 "program_source:121:14: error: call to 'min' is ambiguous
half _16 = min(_15, _13);
^~~
/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.34/include/metal/metal_math:3205:17: note: candidate function
METAL_FUNC half min(half x, half y)
^
/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.34/include/metal/metal_math:4709:18: note: candidate function
METAL_FUNC float min(float x, float y)
^
program_source:194:22: error: call to 'select' is ambiguous
float _86 = (float)select(_84, _17, _85);
^~~~~~
/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.34/include/metal/metal_relational:1096:17: note: candidate function
METAL_FUNC half select(half x, half y, bool c)
^
/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.34/include/metal/metal_relational:1124:18: note: candidate function
METAL_FUNC float select(float x, float y, bool c)
^
program_source:215:15: error: call to 'min' is ambiguous
half _103 = min(_102, _100);
^~~
/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.34/include/metal/metal_math:3205:17: note: candidate function
METAL_FUNC half min(half x, half y)
^
/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.34/include/metal/metal_math:4709:18: note: candidate function
METAL_FUNC float min(float x, float y)
^
program_source:288:23: error: call to 'select' is ambiguous
float _173 = (float)select(_171, _104, _172);
^~~~~~
/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.34/include/metal/metal_relational:1096:17: note: candidate function
METAL_FUNC half select(half x, half y, bool c)
^
/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.34/include/metal/metal_relational:1124:18: note: candidate function
METAL_FUNC float select(float x, float y, bool c)
^
" UserInfo={NSLocalizedDescription=program_source:121:14: error: call to 'min' is ambiguous
half _16 = min(_15, _13);
^~~
/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.34/include/metal/metal_math:3205:17: note: candidate function
METAL_FUNC half min(half x, half y)
^
/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.34/include/metal/metal_math:4709:18: note: candidate function
METAL_FUNC float min(float x, float y)
^
program_source:194:22: error: call to 'select' is ambiguous
float _86 = (float)select(_84, _17, _85);
^~~~~~
/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.34/include/metal/metal_relational:1096:17: note: candidate function
METAL_FUNC half select(half x, half y, bool c)
^
/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.34/include/metal/metal_relational:1124:18: note: candidate function
METAL_FUNC float select(float x, float y, bool c)
^
program_source:215:15: error: call to 'min' is ambiguous
half _103 = min(_102, _100);
^~~
/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.34/include/metal/metal_math:3205:17: note: candidate function
METAL_FUNC half min(half x, half y)
^
/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.34/include/metal/metal_math:4709:18: note: candidate function
METAL_FUNC float min(float x, float y)
^
program_source:288:23: error: call to 'select' is ambiguous
float _173 = (float)select(_171, _104, _172);
^~~~~~
/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.34/include/metal/metal_relational:1096:17: note: candidate function
METAL_FUNC half select(half x, half y, bool c)
^
/System/Library/PrivateFrameworks/GPUCompiler.framework/Versions/32023/Libraries/lib/clang/32023.34/include/metal/metal_relational:1124:18: note: candidate function
METAL_FUNC float select(float x, float y, bool c)
^
}
Error: halide_metal_initialize_kernels: setup failed.