У меня есть следующий код C. На моей машине это время составляет около 13 секунд.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
clock_t begin = clock();
double d = 0;
for (int i = 0; i < 1e9; i++) {
d = 1 + rand() * 5 > 10 ? 4 : rand();
}
clock_t end = clock();
double time_spent = (double) (end - begin) / CLOCKS_PER_SEC;
printf("%f", time_spent);
return EXIT_SUCCESS;
}
Но эта непростая операция, я измеряю доли секунды!
a = np.random.randn(1000, 1000)
b = np.random.randn(1000, 1000)
c = a.dot(b)
Как это возможно, учитывая, что они выполняют одинаковый объем работы (1e9 операций)? Распараллеливание numpy ??
Ваша программа на C имеет if посередине, что часто останавливает процессор.
Вы делаете очень разные операции. Во-первых, ваш Python генерирует псевдослучайные числа 2e6; ваш код C, по крайней мере, 1e9 в дополнение к умножению и сумме, которое выполняют оба кода. Вы бы предпочли поднять тысячу листов бумаги или тысячу ядер? Почему? Разве это не то же самое, тысячи и тысячи?
попробуйте сделать np.random.randn (31623, 31623)
В c вы выполняете более 10 ^ 9 операций rand () из-за вашего состояния в цикле.
Опять же ... Совершенно и совершенно бессмысленно обсуждать производительность, если 1) вы не говорите нам, какую систему вы используете, 2) вы не говорите нам, какой компилятор вы используете, и 3) вы не говорите нам какие варианты оптимизации использовались.
@Lundin: Ваше утверждение о том, что бессмысленно обсуждать производительность без этой информации, противоречит тому факту, что основная причина наблюдаемого поведения OP была правильно диагностирована за два часа до вашего комментария.






Numpy имеет бэкэнды на нескольких языках, таких как C, C++ и Fortran, как указано в их документах
As Numeric has matured and developed into NumPy, people have been able to write more code directly in NumPy. Often this code is fast-enough for production use, but there are still times that there is a need to access compiled code. Either to get that last bit of efficiency out of the algorithm or to make it easier to access widely-available codes written in C/C++ or Fortran)
Так что, если вы не пишете высокооптимизированный код C, скорее всего, он в любом случае будет медленнее.
Ваши программы работают по-другому. Ваша программа C вызывает randкак минимум10^9 раза. кроме того, у вас есть условия для ваших случайностей.
numpy создает 2 массива 1000x1000, а это только 2x10^6. нет условий на случайное значение. скалярное произведение затем добавляет операции O(n^3) (и создание массива), но очень оптимизировано.
Таким образом, вы в основном сравниваете последовательные вызовы rand в C с гораздо меньшим количеством вызовов randn плюс оптимизированная операция (dot) в python.
Чтобы иметь действительный тест, у вас должны быть 2 программы, выполняющие одни и те же операции.
Вы имеете в виду, что программа numpy выполняет только 1 вызов случайной функции для генерации 10 ^ 6 различных случайных записей?
Матричное скалярное произведение принимает O (n ^ 3), что равно 1e9.
Но точка находится вдоль общей размерности 1000. Итак, у нас есть два массива в 10 ^ 6, я с вами. Но точка добавляет еще 10 ^ 3 операций. Вернуться на 10 ^ 9
Numpy, вероятно, сильно оптимизирует точечный продукт для локализации кеша, поэтому я готов поспорить, что его операции 10 ^ 9 выполняются намного быстрее, чем системные вызовы 10 ^ 9 (для случайных) в программе C++.
вы все еще сравниваете разные операции очень. ~10^9rand() вызовы против 10^6nrand() вызовов плюс умножение / создание массива. для реального теста вы должны убедиться, что ваши программы работают точно так же.
@ Arthur-1 random не является системным вызовом.
Обратите внимание, что оба кода безоговорочно выполняют сложение 1e9 и умножение 1e9. Вызовы cca 2e9 rand являются наверху этого. Здесь - источник случайного числа glibc - сложение, умножение и побитовое И (для простейшего ГСЧ).
Глупый, я не знаю, с какой стати я предполагаю, что реализация будет делать системный вызов генератору случайных чисел ОС. Наверное пора спать :)
numpy.dot вызовет базовую библиотеку BLAS в вашей системе, если это возможно.
На какой ОС вы работаете? Если вы работаете в Linux, запустите команду
topиз командной строки при выполнении операции numpy и визуально проверьте, сколько ядер используется. Хотя я подозреваю, что numpy не использует параллелизм без вашего явного указания.