i在具有BLAS功能,模板操作员和迭代求解器的高性能代码上工作。为了进行性能测量,我们使用手动计算的"有用"拖放数量,然后除以算法所需的时间。这可以使用"有用"的性能。
模板是类,因此我可以添加virtual int get_flops() const
成员功能。在迭代求解器中,我只会从各种模板呼叫中加起来拖鞋。
但是,BLAS例程是函数。它们就像void copyVector(V a, const V b)
。我想将整数0
与此功能相关联。使用返回值似乎是一个快速修复,但我可能想稍后再添加另一个注释。
一种选择是将这些选择转变为使用operator()
的Singleton课程,但这感觉就像违反了开放式原理(OCP(。是否有类型的特质我可以为函数做的?
我可能会做更多类似的事情:
#include <type_traits>
#include <iostream>
struct dummy { };
template <class T>
struct flop_map {
static int value;
};
template <class T>
int flop_map<T>::value;
#define FOO_ID(foo) std::integral_constant<decltype(&foo), &foo>
void blas_routine(double *const, double const *const) {}
void other(int, int) {}
int main() {
flop_map<FOO_ID(blas_routine)>::value = 0;
flop_map<FOO_ID(other)>::value = 4;
std::cout << flop_map<FOO_ID(blas_routine)>::value << std::endl;
std::cout << flop_map<FOO_ID(other)>::value << std::endl;
}
[live demo]
您可以创建Global unordered_map,并使用功能指针进行关联整数。这样的东西:
std::unordered_map<void(*)(void), int> tmp;
据我所记得的标准保证,所有类型的功能指针具有相同的大小,并且由于您只使用功能指针将索引索引到映射中,因此您可以将任何功能指针(而不是指针to to member tho(void void(**((void(并从unordered_map中设置/检索。
基于RadosławCybulski的答案,我将其扩展到完整的工作版本:
#include <iostream>
#include <unordered_map>
template <typename Annotation>
class FunctionAnnotation {
public:
template <typename R, typename... Args>
Annotation get(R (*func)(Args...)) {
return map_.at(strip(func));
}
template <typename R, typename... Args>
void set(R (*func)(Args...), Annotation annotation) {
map_[strip(func)] = annotation;
}
private:
// Basic function pointer type.
typedef void (*VoidFunc)();
// Type stripping function that will take a function pointer and return a
// function with the wrong but unified type.
template <typename R, typename... Args>
VoidFunc strip(R (*func)(Args...)) {
return reinterpret_cast<VoidFunc>(func);
}
// The map with annotation values.
std::unordered_map<VoidFunc, Annotation> map_;
};
FunctionAnnotation<int> flop_map;
// Some example functions.
void blas_routine(double *const dest, double const *const src) {}
void other(int a, int b) {}
int main() {
// Populate that map.
flop_map.set(blas_routine, 0);
flop_map.set(other, 4);
// Later on use that.
std::cout << flop_map.get(blas_routine) << std::endl;
std::cout << flop_map.get(other) << std::endl;
}
这在C 11和C 14模式中用GCC干净地编译。输出是预期的:
0
4