当然可以。
最好的方法是让函数完成完整的工作,并在运行时在它们中进行选择。这可行,但不是最佳的:
typedef enum
{
calc_type_invalid = 0,
calc_type_plain,
calc_type_sse,
calc_type_avx,
calc_type_max // not a valid value
} calc_type;
void do_my_calculation(float const *input, float *output, size_t len, calc_type ct)
{
float f;
size_t i;
for (i = 0; i < len; ++i)
{
switch (ct)
{
case calc_type_plain:
// plain calculation here
break;
case calc_type_sse:
// SSE calculation here
break;
case calc_type_avx:
// AVX calculation here
break;
default:
fprintf(stderr, "internal error, unexpected calc_type %d", ct);
exit(1);
break
}
}
}
每次通过循环时,代码都会执行switch 语句,这只是开销。一个非常聪明的编译器理论上可以为您修复它,但最好自己修复它。
改为编写三个单独的函数,一个用于普通函数,一个用于 SSE,一个用于 AVX。然后在运行时决定运行哪一个。
对于加分,在“调试”构建中,使用 SSE 和普通版进行计算,并断言结果足够接近以提供信心。写明文版本,不是为了速度,而是为了正确;然后用它的结果来验证你聪明的优化版本是否得到了正确的答案。
传奇人物约翰卡马克推荐后一种方法;他称之为“并行实现”。阅读his essay 了解它。
所以我建议你先写普通版本。然后,返回并开始使用 SSE 或 AVX 加速重写部分应用程序,并确保加速版本给出正确的答案。 (有时,普通版本可能有加速版本没有的错误。拥有两个版本并比较它们有助于发现任何一个版本的错误。)