【问题标题】:Faster way to calculate modulo when you have a previous answer?当您有先前的答案时,更快地计算模数的方法?
【发布时间】:2018-10-31 10:51:07
【问题描述】:

我有大量的模数计算要执行。基本计算如下:

const uint64_t start;       // Some "large" number that does NOT change
uint32_t prime[bigNumber];  // Precalculated sequential prime numbers (generated on the fly from a bit compaction storage method for space reasons).
uint64_t answer[bigNumber]; // The "modulo" answers

for (uint64_t i = 0; i < bigNumber; i++) {
   uint32_t factor = prime[i];
   answer[i] = (factor - 1) - ((start - 1) % factor);
}

注意:start 通常比 prime[i] 大得多。

是否有更快的方法来计算“答案”,而无需为每次迭代执行模/除法(AKA 可以知道 answer[i - 1] 帮助您更快地获得 answer[i])?任何其他改进或建议将不胜感激。

【问题讨论】:

  • 也许你可以从this源应用快速模数。
  • 除非prime 序列和/或start 有一些特殊的属性,我怀疑没有更快的方法。通常给定足够大的start,您可以将answer[i] 设为某些i 的任何值,而使所有其他answers 相同(请参阅Chinese remainder theorem)。
  • 加速此例程的唯一可行方法是并行运行其中的一部分。
  • 这确实是边缘情况,但用浮点算术模拟模更快(已经在标量代码中)并且还可以矢量化
  • 我的实现已经使用了多线程并行(未显示)。至于数据并行性或矢量化,我遇到的问题是“开始”可以超过 2^53 -1(最大 int 而不会丢失转换精度)。除法仅存在于非整数运算中的 x86 向量化内在函数。除了从整数到双精度的转换(反之亦然)会减慢它的速度,向量化也仅限于一次只有 2 个双精度。是的,向量双除法比单个整数除法更快。所有伟大的想法,但对我有一些限制。

标签: algorithm performance math optimization simd


【解决方案1】:

我想写下部分答案来回应上述一些 cmets。一次做多个模组会有所帮助。

  if (start < (1ULL << DBL_MANT_DIG)) {
    __m256d div1 = _mm256_broadcastsd_pd(_mm_cvtsi64_sd(_mm_setzero_pd(), start - 1));
    __m128i one  = _mm_set1_epi32(-1);
    __m128i fact = *(__m128i *)(&prime[i]);

    __m256d div2 = _mm256_cvtepi32_pd(fact);

    __m128i rem = _mm256_cvtpd_epi32(_mm256_fnmadd_pd(
                  _mm256_floor_pd(_mm256_div_pd(div1, div2)), div2, div1));

    *(__m256i *)(&answer[i]) = _mm256_cvtepu32_epi64(_mm_sub_epi32(fact,
                               _mm_sub_epi32(rem, one)));
  }

如果您对此部分答案有改进,请发表评论。

【讨论】:

  • 将 _mm256_mul_pd 和 _mm256_sub_pd 替换为 _mm256_fnmadd_pd
  • 如果您使用-mfma-mavx 编译,一些编译器可以为您将_mm256_mul_pd_mm256_sub_pd 融合到FMA 中。 (或者更好地设置调整选项,使用-march=haswell 或更高版本。)但是如果你不关心没有 FMA 的 AVX,或者你关心的编译器做得不好,那么一定要使用 FMA 内在函数.
猜你喜欢
  • 2012-07-03
  • 2014-08-01
  • 2021-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多