Halide icon indicating copy to clipboard operation
Halide copied to clipboard

Runtime error (ambiguous function call) for float16 on Metal backend

Open yyuting opened this issue 9 months ago • 0 comments

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.

yyuting avatar May 29 '24 21:05 yyuting