Почему Clang выделяет std :: complex так быстро? - PullRequest
2 голосов
/ 11 марта 2020

Я проверил производительность выделения памяти для массива std::complex<double> с использованием компиляторов G CC, Clang и Intel C ++. Я обнаружил, что между этими компиляторами есть существенная разница в производительности c. Clang на несколько порядков быстрее, чем другие компиляторы.

Может кто-нибудь выяснить причину? Спасибо! Код теста, среда тестирования и подробности результатов теста прилагаются ниже.

Вложения

Вот код теста производительности:

#include <iostream>
#include <complex>

#include <sys/time.h>
#include <stdlib.h>


double GetWallTime(void) {
  struct timeval time;
  if (gettimeofday(&time, NULL)) { return 0; }
  return (double)time.tv_sec + (double)time.tv_usec * .000001;
}


int main(int argc, char *argv[]) {
  auto size = atol(argv[1]);

  auto time_now = GetWallTime();
  auto double_array = new double [size];
  std::cout << "allocate double[" << size << "]: use "
            << GetWallTime() - time_now   << " sec" << std::endl;
  delete[] double_array;

  time_now = GetWallTime();
  auto c99cplx_array = new double _Complex [size];
  std::cout << "allocate double _Complex[" << size << "]: use "
            << GetWallTime() - time_now  << " sec" << std::endl;
  delete[] c99cplx_array;

  time_now = GetWallTime();
  auto stdcplx_array = new std::complex<double> [size];
  std::cout << "allocate std::complex<double>[" << size << "]: use "
            << GetWallTime() - time_now         << " sec" << std::endl;
  delete[] stdcplx_array;
  return 0;
}

На компьютере Linux с процессорами Xeon E5-2680 v2 * 2 и памятью 64G DDR3 я компилирую этот код, используя эти три компилятора, и запускаю тест. Я получаю следующие результаты:

Использование g++ 7.5.0 с --std=c++11 -O3 флажками:

allocate double[10000000]: use 5.6982e-05 sec
allocate double _Complex[10000000]: use 1.71661e-05 sec
allocate std::complex<double>[10000000]: use 0.0911679 sec

Использование icpc 19.1.0.166 с --std=c++11 -O3 флажками:

allocate double[10000000]: use 7.41482e-05 sec
allocate double _Complex[10000000]: use 1.69277e-05 sec
allocate std::complex<double>[10000000]: use 0.087034 sec

Используйте clang++ с версией

> clang++ --version
Intel(R) oneAPI DPC++ Compiler 2021.1-beta03 (2019.10.0.1121)
Target: x86_64-unknown-linux-gnu
Thread model: posix

с --std=c++11 -O3 флажками:

allocate double[10000000]: use 4.19617e-05 sec
allocate double _Complex[10000000]: use 9.53674e-07 sec
allocate std::complex<double>[10000000]: use 1.19209e-06 sec

1 Ответ

3 голосов
/ 11 марта 2020

Потому что ваш тест ужасен. Clang просто полностью удалил новый / удалить, потому что это бессмысленно. Вы эффективно профилируете это:

#include <complex>
int main() {

    auto ptr = new std::complex<double>[1000];
    delete [] ptr;
    return 0;
}

Какой кланг правильно уменьшен до:

main:                                   # @main
        xor     eax, eax
        ret

https://godbolt.org/z/4JjXfh

g cc с другой стороны, выделяет и освобождает память. Вы не тестируете скорость выделения, вы тестируете бургер. Не используйте микро-тесты, как это, вместо этого используйте профилировщик для фактический код .

Если вы хотите профилировать это, выполните:

volatile auto stdcplx_array = new std::complex<double> [size];

, который обеспечит точный тест для каждого компилятора (не то, что ваш тест стоит того - он просто уменьшится до новый + memset + delete) .

...