Skip to content

Commit ca7db61

Browse files
committed
optimise: Get rid of the switch statement being executed each time a index needs to be determined.
When creating the object the type and a function pointer is stored which will be used to call the correct function which has the `Type` as template for the switch statement. In theory the compiler should be smart enough to compile the switch statment out for the loop and thus it is only necessary then to get the data. The overhead added for determining the data at a certain index should now be a lot similar to before the offset and stride was added when looping over each index. Implemented this in [godbolt](https://godbolt.org/z/qWrYq6je1) for testing and comparing what the compiler does
1 parent 2ab2dd0 commit ca7db61

File tree

1 file changed

+57
-24
lines changed

1 file changed

+57
-24
lines changed

implot_items.cpp

Lines changed: 57 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2376,6 +2376,31 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES()
23762376
// [SECTION] PlotHeatmap
23772377
//-----------------------------------------------------------------------------
23782378

2379+
template<typename T, typename I, int Type>
2380+
IMPLOT_INLINE T HeatmapIndexData(const T* const data, I idx, int count, int major, int minor, int num_major, int num_minor, int major_offset, int minor_offset, int major_stride, int minor_stride)
2381+
{
2382+
// Get the data based based on the type
2383+
switch(Type) {
2384+
case 15: return data[idx]; // No offset or stride
2385+
case 14: return data[(((minor + minor_offset) < num_minor ? minor_offset : (minor_offset - num_minor)) + idx) % count]; // Minor offset
2386+
case 13: return data[(major_offset + idx) % count]; // Major offset
2387+
case 12: return data[(major_offset + ((minor + minor_offset) < num_minor ? minor_offset : (minor_offset - num_minor)) + idx) % count]; // Major+minor offset
2388+
case 11: return *(const T*)(const void*)((const unsigned char*)data + (size_t)((idx)) * minor_stride); // Minor stride
2389+
case 10: return *(const T*)(const void*)((const unsigned char*)data + (size_t)((((minor + minor_offset) < num_minor ? minor_offset : (minor_offset - num_minor)) + idx) % count) * minor_stride); // Minor stride and minor offset
2390+
case 9: return *(const T*)(const void*)((const unsigned char*)data + (size_t)((major_offset + idx) % count) * minor_stride); // Minor stride and major offset
2391+
case 8: return *(const T*)(const void*)((const unsigned char*)data + (size_t)((major_offset + ((minor + minor_offset) < num_minor ? minor_offset : (minor_offset - num_minor)) + idx) % count) * minor_stride); // Minor stride and major + minor offset
2392+
case 7: return *(const T*)(const void*)((const unsigned char*)data + (size_t)((major)) * major_stride + minor * sizeof(T)); // Major stride
2393+
case 6: return *(const T*)(const void*)((const unsigned char*)data + (size_t)((major)) * major_stride + ((minor + minor_offset) % num_minor) * sizeof(T)); // Major stride and minor offset
2394+
case 5: return *(const T*)(const void*)((const unsigned char*)data + (size_t)((major + major_offset) % num_major) * major_stride + minor * sizeof(T)); // Major stride and major offset
2395+
case 4: return *(const T*)(const void*)((const unsigned char*)data + (size_t)((major + major_offset) % num_major) * major_stride + ((minor + minor_offset) % num_minor) * sizeof(T)); // Major stride and major+minor offset
2396+
case 3: return *(const T*)(const void*)((const unsigned char*)data + (size_t)((major)) * major_stride + (size_t)((minor)) * minor_stride); // Major+minor stride
2397+
case 2: return *(const T*)(const void*)((const unsigned char*)data + (size_t)((major)) * major_stride + (size_t)((minor + minor_offset) % num_minor) * minor_stride); // Major+minor stride and minor offset
2398+
case 1: return *(const T*)(const void*)((const unsigned char*)data + (size_t)((major + major_offset) % num_major) * major_stride + (size_t)((minor)) * minor_stride); // Major+minor stride and major offset
2399+
case 0: return *(const T*)(const void*)((const unsigned char*)data + (size_t)((major + major_offset) % num_major) * major_stride + (size_t)((minor + minor_offset) % num_minor) * minor_stride); // Major+minor stride and major+minor offset
2400+
default: return T(0);
2401+
}
2402+
}
2403+
23792404
template <typename T>
23802405
struct HeatmapIndexerIdx {
23812406
HeatmapIndexerIdx(const T* data, int num_major, int num_minor, int major_offset, int minor_offset, int major_stride, int minor_stride) :
@@ -2385,38 +2410,46 @@ struct HeatmapIndexerIdx {
23852410
MajorOffset((major_stride == int(sizeof(T)) * num_minor) ? ImPosMod(num_minor * major_offset, num_minor * num_major) : ImPosMod(major_offset, num_major)),
23862411
MinorOffset(ImPosMod(minor_offset, num_minor)),
23872412
MajorStride(major_stride),
2388-
MinorStride(minor_stride),
2389-
Type(((MinorOffset == 0) << 0) | ((MajorOffset == 0) << 1) | ((MinorStride == int(sizeof(T))) << 2) | ((MajorStride == int(sizeof(T)) * num_minor) << 3))
2390-
{ }
2413+
MinorStride(minor_stride)
2414+
{
2415+
const int type = ((MinorOffset == 0) << 0) | ((MajorOffset == 0) << 1) | ((MinorStride == int(sizeof(T))) << 2) | ((MajorStride == int(sizeof(T)) * num_minor) << 3);
2416+
// Get the data based based on the type
2417+
switch(type) {
2418+
case 15: IndexDataFunc = &(HeatmapIndexData<T, int, 15>); break;
2419+
case 14: IndexDataFunc = &(HeatmapIndexData<T, int, 14>); break;
2420+
case 13: IndexDataFunc = &(HeatmapIndexData<T, int, 13>); break;
2421+
case 12: IndexDataFunc = &(HeatmapIndexData<T, int, 12>); break;
2422+
case 11: IndexDataFunc = &(HeatmapIndexData<T, int, 11>); break;
2423+
case 10: IndexDataFunc = &(HeatmapIndexData<T, int, 10>); break;
2424+
case 9: IndexDataFunc = &(HeatmapIndexData<T, int, 9>); break;
2425+
case 8: IndexDataFunc = &(HeatmapIndexData<T, int, 8>); break;
2426+
case 7: IndexDataFunc = &(HeatmapIndexData<T, int, 7>); break;
2427+
case 6: IndexDataFunc = &(HeatmapIndexData<T, int, 6>); break;
2428+
case 5: IndexDataFunc = &(HeatmapIndexData<T, int, 5>); break;
2429+
case 4: IndexDataFunc = &(HeatmapIndexData<T, int, 4>); break;
2430+
case 3: IndexDataFunc = &(HeatmapIndexData<T, int, 3>); break;
2431+
case 2: IndexDataFunc = &(HeatmapIndexData<T, int, 2>); break;
2432+
case 1: IndexDataFunc = &(HeatmapIndexData<T, int, 1>); break;
2433+
case 0: IndexDataFunc = &(HeatmapIndexData<T, int, 0>); break;
2434+
}
2435+
}
23912436

23922437
template <typename I> IMPLOT_INLINE double operator()(I idx, int count, int major, int minor, int num_major, int num_minor) const {
23932438
return (double)GetData(idx, count, major, minor, num_major, num_minor);
23942439
}
23952440

23962441
template <typename I> IMPLOT_INLINE T GetData(I idx, int count, int major, int minor, int num_major, int num_minor) const {
2397-
// Get the data based based on the type
2398-
switch (Type) {
2399-
case 15: return Data[idx]; // No offset or stride
2400-
case 14: return Data[(((minor + MinorOffset) < num_minor ? MinorOffset : (MinorOffset - num_minor)) + idx) % count]; // Minor offset
2401-
case 13: return Data[(MajorOffset + idx) % count]; // Major offset
2402-
case 12: return Data[(MajorOffset + ((minor + MinorOffset) < num_minor ? MinorOffset : (MinorOffset - num_minor)) + idx) % count]; // Major+minor offset
2403-
case 11: return *(const T*)(const void*)((const unsigned char*)Data + (size_t)((idx)) * MinorStride); // Minor stride
2404-
case 10: return *(const T*)(const void*)((const unsigned char*)Data + (size_t)((((minor + MinorOffset) < num_minor ? MinorOffset : (MinorOffset - num_minor)) + idx) % count) * MinorStride); // Minor stride and minor offset
2405-
case 9: return *(const T*)(const void*)((const unsigned char*)Data + (size_t)((MajorOffset + idx) % count) * MinorStride); // Minor stride and major offset
2406-
case 8: return *(const T*)(const void*)((const unsigned char*)Data + (size_t)((MajorOffset + ((minor + MinorOffset) < num_minor ? MinorOffset : (MinorOffset - num_minor)) + idx) % count) * MinorStride); // Minor stride and major + minor offset
2407-
case 7: return *(const T*)(const void*)((const unsigned char*)Data + (size_t)((major)) * MajorStride + minor * sizeof(T)); // Major stride
2408-
case 6: return *(const T*)(const void*)((const unsigned char*)Data + (size_t)((major)) * MajorStride + ((minor + MinorOffset) % num_minor) * sizeof(T)); // Major stride and minor offset
2409-
case 5: return *(const T*)(const void*)((const unsigned char*)Data + (size_t)((major + MajorOffset) % num_major) * MajorStride + minor * sizeof(T)); // Major stride and major offset
2410-
case 4: return *(const T*)(const void*)((const unsigned char*)Data + (size_t)((major + MajorOffset) % num_major) * MajorStride + ((minor + MinorOffset) % num_minor) * sizeof(T)); // Major stride and major+minor offset
2411-
case 3: return *(const T*)(const void*)((const unsigned char*)Data + (size_t)((major)) * MajorStride + (size_t)((minor)) * MinorStride); // Major+minor stride
2412-
case 2: return *(const T*)(const void*)((const unsigned char*)Data + (size_t)((major)) * MajorStride + (size_t)((minor + MinorOffset) % num_minor) * MinorStride); // Major+minor stride and minor offset
2413-
case 1: return *(const T*)(const void*)((const unsigned char*)Data + (size_t)((major + MajorOffset) % num_major) * MajorStride + (size_t)((minor)) * MinorStride); // Major+minor stride and major offset
2414-
case 0: return *(const T*)(const void*)((const unsigned char*)Data + (size_t)((major + MajorOffset) % num_major) * MajorStride + (size_t)((minor + MinorOffset) % num_minor) * MinorStride); // Major+minor stride and major+minor offset
2415-
default: return T(0);
2416-
}
2442+
return IndexDataFunc(Data, idx, count, major, minor, num_major, num_minor, MajorOffset, MinorOffset, MajorStride, MinorStride);
24172443
}
24182444
const T* const Data;
2419-
const int MajorOffset, MinorOffset, MajorStride, MinorStride, Type;
2445+
const int MajorOffset, MinorOffset, MajorStride, MinorStride;
2446+
2447+
template<typename K, typename I>
2448+
struct IndexerTypeHelper
2449+
{
2450+
typedef K (*type)(const K* const, I, int, int, int, int, int, int, int, int, int);
2451+
};
2452+
typename IndexerTypeHelper<T, int>::type IndexDataFunc;
24202453
};
24212454

24222455
template <typename T, typename _Indexer>

0 commit comments

Comments
 (0)