Недавно я приобрел компьютер с двойной загрузкой кода на С++. В окнах я использую компилятор Intel С++ и g++ на linux.
Мои программы состоят в основном из вычислений (алгоритм итерации с фиксированной точкой с численным интегрированием и т.д.).
Мне показалось, что я могу работать с окнами на моем Linux, но до сих пор я этого не делаю: для одного и того же кода программа, скомпилированная с g++, примерно в 2 раза медленнее, чем у компилятора Intel. Из того, что я читал, icc может быть быстрее, может быть, даже до 20-30% прибыли, но я ничего не читал о том, что он в два раза быстрее (и вообще я действительно читал, что оба они должны быть эквивалентными).
Сначала я использовал флаги, которые примерно эквивалентны:
icl/openmp/I "C:\boost_1_61_0" /fast program.cpp
и
g++ -o program program.cpp -std = С++ 11 -fopenmp -O3 -ffast-math
Следуя советам из нескольких других тем, я попытался добавить/заменить несколько других флагов, таких как: -funsafe-math-optimizations, -march = native, -fwhole-program, -Ofast и т.д. с небольшим (или отсутствием) усилением производительности.
Действительно ли icc быстрее или я что-то упускаю? Я новичок в Linux, поэтому не знаю, может, я забыл что-то установить (например, драйвер) или изменить какой-либо вариант в g ++? Я понятия не имею, нормальная ситуация или нет, поэтому я предпочитаю спросить. Тем более, что я предпочитаю использовать linux для кодирования в идеале, поэтому я предпочел бы, чтобы это было быстро.
EDIT: Я решил установить последний Linux-компилятор (Intel Compiler С++ 17, update4) на linux для проверки. Я получаю смягчаемые результаты: он НЕ делает лучше, чем gcc (на самом деле хуже). Я выполнил перекрестное сравнение linux/windows - icc/gcc - распараллеливал или нет, используя флаги, упомянутые ранее в сообщении (чтобы делать прямые сравнения), вот мои результаты (время для запуска 1 итерации, измеренное в мс):
-
Обычный цикл, без распараллеливания:
- Окна
gcc = 122074; icc = 68799 - Linux:
gcc = _91042; icc = 92102
- Окна
-
Параллельная версия:
- Окна
gcc = 27457; icc = 19800 - Linux:
gcc = 27000; icc = 30000
- Окна
Подводя итог: это немного беспорядок. В linux gcc, кажется, всегда быстрее, чем icc, особенно когда речь идет о параллелизации (я запускал его для более длительной программы, разница намного выше, чем здесь). В окнах это противоположное и icc явно доминирует gcc, особенно когда нет распараллеливания (в этом случае gcc занимает очень много времени для компиляции).
Самая быстрая компиляция выполняется с помощью распараллеливания и icc на окнах. Я не понимаю, почему я не могу воспроизвести это на linux. Что мне нужно сделать (ubuntu 16.04), чтобы помочь скрепить мои процессы?
Другое отличие состоит в том, что в Windows я использую более старый Intel-композитор (Composer XE 2013) и вызываю 'ia32' вместо intel64 (который я должен использовать), а на linux я использую последний версию, которую я установил вчера. И на Linux папка Intel Compiler 17 находится на моем втором hdd (а не на моем ssd, на котором устанавливается Linux). Я не знаю, может ли это замедлить работу.
Любая идея, из которой может возникнуть проблема?
Изменить: Точное оборудование: Intel (R) Core (TM) i7-4710HQ CPU @2.50GHz, 8 CPU, 4 ядра, 2 потока на ядро, архитектура x86_64 - Linux Ubuntu 16.04 с gcc 5.4.1 и Intel Compiler 17 (update4) - Windows 8.1, Intel Composer 2013
Изменить: Код очень длинный, вот форма цикла, который я тестирую (т.е. только одна итерация моей итерации с фиксированной точкой). Это очень классический, я думаю... не уверен, что он может принести что-нибудь в тему.
// initialization of all the objects...
// length_grid1 is about 2000
vector< double > V_NEXT(length_grid1), PRICE_NEXT(length_grid1);
double V_min, price_min;
#pragma omp parallel
{
#pragma omp for private(V_min, price_min, i, indexcurrent, alpha, beta)
for (i = 0; i < length_grid1; i++) {
indexcurrent = indexsum[i];
V_min = V_compute(&price_min, indexcurrent, ...);
V_NEXT[indexcurrent] = V_min; PRICE_NEXT[indexcurrent] = price_min;
}
}// end parallel
где функция V_compute - это классический и простой алгоритм оптимизации (настраиваемый золотой поиск), возвращающий оптимальное значение и его аргумент:
double V_compute(double *xmin, int row_index, ... ) {
double x1, x2, f1, f2, fxmin;
// golden_ratio=0.61803399;
x1 = upper_bound - golden_ratio*(upper_bound - lower_bound);
x2 = lower_bound + golden_ratio*(upper_bound - lower_bound);
// Evaluate the function at the test points
f1 = intra_value(x1, row_index, ...);
f2 = intra_value(x2, row_index, ...);
while (fabs(upper_bound - lower_bound) > tolerance) {
if (f2 > f1){
upper_bound = x2; x2 = x1; f2 = f1;
x1 = upper_bound - golden_ratio*(upper_bound - lower_bound);
f1 = intra_value(x1, row_index, ...);
} else {
lower_bound = x1; x1 = x2; f1 = f2;
x2 = lower_bound + golden_ratio*(upper_bound - lower_bound);
f2 = intra_value(x2, row_index, ...);
}
}
// Estimated minimizer = (lower bound + upper bound) / 2
*xmin = (lower_bound + upper_bound)/2;
fxmin = intra_value(*xmin, row_index, ...);
return - fxmin; }
Оптимизированная функция (intra_value) довольно сложна с точки зрения вычисления (выберите точку сетки (row_index) из предварительно скомпилированной сетки, затем включите много числового интегрирования и т.д.).