2015-08-02 3 views
-5

Я пытаюсь создать матрицу случайных чисел 5000 на 5000. Вот то, что я делаю с MATLAB:C++ медленнее, чем MATLAB

for i = 1:100 
    rand(5000) 
end 

И вот что я делаю в C++:

#include <iostream> 
#include <stdlib.h> 
#include <time.h> 
#include <ctime> 

using namespace std; 


int main(){ 

    int N = 5000; 
    double ** A = new double*[N]; 
    for (int i=0;i<N;i++) 
     A[i] = new double[N]; 


    srand(time(NULL)); 

    clock_t start = clock(); 
    for (int k=0;k<100;k++){ 
     for (int i=0;i<N;i++){ 
      for (int j=0;j<N;j++){ 
       A[i][j] = rand(); 
      } 
     } 
    } 

    cout << "T="<< (clock()-start)/(double)(CLOCKS_PER_SEC/1000)<< "ms " << endl; 

} 

MATLAB занимает около 38 секунд, в то время как C++ занимает около 90 секунд. В другом вопросе люди выполнили тот же код и получили одинаковые скорости как для C++, так и для MATLAB.

Я использую Visual C++ со следующими оптимизациями http://i.stack.imgur.com/HXP8i.png

Я хотел бы узнать, что я здесь отсутствует? Спасибо вам за помощь.

EDIT: Вот ключевая вещь, хотя ... Why MATLAB is faster than C++ in creating random numbers?

В этом вопросе, люди дали мне ответы, где их C++ скорости такие же, как MATLAB. Когда я использую тот же код, я получаю более худшие скорости, и я пытаюсь понять, почему.

+4

Это не эквивалент. В случае C++ у вас есть несмежный массив, и каждый вызов 'rand' требует последующего преобразования в' double'. По крайней мере, попробуйте запустить со смежным массивом (т. Е. 'Double * A = new double [5000 * 5000]'). –

+0

Также он должен читать 'CLOCKS_PER_SEC/1000.0'. 'CLOCKS_PER_SEC' определяется как' (long) 1000' на VS2015, но лучше оставаться на безопасной стороне, если любой другой компилятор/среда использует разные значения. – Banex

+1

Вы скомпилировали C++ с включенной оптимизацией? – juanchopanza

ответ

3

Ваш тест является ошибочным, как другие отметили, и даже не обращается к заявлению, сделанному по названию. Вы сравниваете встроенную функцию Matlab с C++, а не сам код Matlab, который на самом деле выполняется в 100 раз медленнее, чем C++.Matlab просто обертка вокруг библиотеки BLAS/LAPACK в C/Fortran, так можно было бы ожидать, сценарий Matlab и грамотно написана C++, чтобы быть приблизительно эквивалентны, и на самом деле они являются: Этот код в MatLab 2007B

tic; A = rand(5000); toc 

выполняется в 810 мс на моей машине, и это

#include <iostream> 
#include <stdlib.h> 
#include <time.h> 
#include <ctime> 

#define N 5000 
int main() 
{ 
    srand(time(NULL)); 

    clock_t start = clock(); 

    int num_rows = N, 
     num_cols = N; 
    double * A = new double[N*N]; 
    for (int i=0; i<N*N; ++i) 
     A[i] = rand(); 

    std::cout << "T="<< (clock()-start)/(double)(CLOCKS_PER_SEC/1000)<< "ms " << std::endl; 

    return 0; 
} 

исполняет в 830 мс. Небольшое преимущество для внутреннего RNG Matlab по сравнению с rand() не слишком удивительно. Обратите внимание также на единую индексацию. Вот так Matlab делает это, внутренне. Затем он использует умную систему индексирования (разработанную другими), чтобы дать вам матричный интерфейс для данных.

+0

такие же коды выполняются в 830 мс (C++), а matlab - в 343 мс. Я пытаюсь понять эту большую разницу. – radres

+1

@radres Используете ли вы более позднюю версию Matlab? Я думаю, что более свежие RNG сохраняют больше состояний между вызовами и способны достичь большей эффективности.В этом случае правильный эквивалент C++ не будет «rand()», но что-то из [std :: random] (http://www.cplusplus.com/reference/random/) –

+0

да, мой R2014b. Возможно, именно по этой причине это происходит быстрее. – radres

3

В вашем коде на C++ вы делаете 5000 выделений двойной [5000] в куче. Вероятно, вы получите гораздо лучшую скорость, если бы вы сделали одно выделение двойного [25000000], а затем сделаете свою собственную арифметику, чтобы преобразовать ваши 2 индекса в один.

+0

, но вот в чем проблема: люди используют один и тот же код и получают одинаковые скорости как на C++, так и на matlab. Я этого не понимаю. – radres

+5

@radres Почему бы вам не спросить этих людей? – juanchopanza

0

Я считаю, что MATLAB использует несколько ядер процессора на вашей машине. Вы пытаетесь написать многопоточную версию и измерить разницу?

Кроме того, качество (псевдо) случайного также будет иметь небольшое различие (но не так много).

+0

Я попытался использовать parallel_for, но, конечно, скорость еще быстрее, когда я запускаю либо matlab, либо C++, они используют только 1 ядро ​​процессора. И снова есть другие люди, которые используют один и тот же код и получают более быстрые скорости C++ по сравнению с моими. Я не понимаю, что я делаю неправильно – radres

+0

Как и другие предлагаемые, ваш макет памяти не соприкасается, вы также тратите косвенную де-ссылку на каждый двойной. Это может значительно повредить производительность и вызвать загрязнение кеша. –

+1

Matlab не использует несколько ядер. Существует только одно состояние для потока случайных чисел, к которому можно манипулировать только по одному потоку за раз. – Daniel

0

По моему опыту,

  • Сначала проверьте, что вы исполняете свой C++ код в режиме выпуска, а не в режиме отладки. (Хотя я вижу на картинке, что вы находитесь в режиме детекции)
  • Рассмотрите параллелизацию MPI.
  • Помните, что MATLAB оптимизирован и скомпилирован с компилятором Intel, который производит более быстрые исполняемые файлы. Вы также можете попробовать более продвинутые компиляторы, если можете себе это позволить.
  • Последнее, что вы можете создать агрегирование цикла, используя функцию для генерации комбинаций i, j в одном цикле. (В питоне это обычная практика задается функцией product из itertools библиотеки, см this)

Я надеюсь, что это помогает.

Смежные вопросы