Taichi: [Refactor] Use switch-case instead of "static std::map" in taichi/lang_util.cpp

Created on 22 Aug 2020  路  4Comments  路  Source: taichi-dev/taichi

Where to refactor
taichi/lang_util.cpp has quite a few functions (e.g., data_type_name, data_type_format) that uses a static std::map to store input-output mapping.

https://github.com/taichi-dev/taichi/blob/a58a9af78b3c2708178db11499ff0796f8ce338f/taichi/lang_util.cpp#L67-L88

What's wrong with the current design
When multiple threads are calling the function with the static map uninitialized, there will be parallel writes to the "std::map". This may cause a segmentation fault.

How to refactor

  • Simply use C-syntax switch-case instead of "std::map"
  • Still make use of macros to minimize changes

Example
The code above should be changed into something like

std::string data_type_name(DataType t) {
  switch (t) {

#define REGISTER_DATA_TYPE(i, j) \
  case DataType::i:              \
    return #j;

    REGISTER_DATA_TYPE(f16, float16);
    REGISTER_DATA_TYPE(f32, float32);
    REGISTER_DATA_TYPE(f64, float64);
    REGISTER_DATA_TYPE(u1, int1);
    REGISTER_DATA_TYPE(i8, int8);
    REGISTER_DATA_TYPE(i16, int16);
    REGISTER_DATA_TYPE(i32, int32);
    REGISTER_DATA_TYPE(i64, int64);
    REGISTER_DATA_TYPE(u8, uint8);
    REGISTER_DATA_TYPE(u16, uint16);
    REGISTER_DATA_TYPE(u32, uint32);
    REGISTER_DATA_TYPE(u64, uint64);
    REGISTER_DATA_TYPE(gen, generic);
    REGISTER_DATA_TYPE(unknown, unknown);
#undef REGISTER_DATA_TYPE
    default:
      TI_NOT_IMPLEMENTED
  }
}

Additional comments

This is a good starting point for newcomers. Please leave a note if you have contributed < 3 PRs and to take this :-)
Open a draft PR if you want early feedback. It is suggested to ask for a review from me after the first function is refactored before apply your modification to all functions in that file.

good first issue

Most helpful comment

Hello! I've left one PR so far, and I'd be interested in taking this.

All 4 comments

Hello! I've left one PR so far, and I'd be interested in taking this.

A lot of thanks to @aryansoman for refactoring most of the functions! Now we are almost there, the only function left is

https://github.com/taichi-dev/taichi/blob/c3f1a5d1899500eb08facca78fa1373e279cb692/taichi/lang_util.cpp#L306-L336

Suggested solution:

Let's not use switch case in this special case.

Note that std::map<std::pair<DataType, DataType>, DataType> is safe for parallel reading but not parallel writing. We are good as long as we initialize a class TypePromotionMapping, which contains the std::map and initializes everything before we do any query. This can be done if we create a global variable TypePromotionMapping type_promotion_mapping so that its initializer is always called before promoted_type (which then calls something like type_promotion_mapping::query(DataType, DataType).

Hi, I think it is not a difficult work, let me take it! :)

This is fully done. A lot of thanks to @Hanke98 and @aryansoman!

Was this page helpful?
0 / 5 - 0 ratings