2013-10-03 3 views
2

Я создаю базу данных с использованием C#. Проблема в том, что у меня близко к 4 миллионам данных, и для заполнения базы данных требуется много времени (может быть, несколько месяцев). Код выглядит примерно так.Параллельное вычисление элементов массива на GPU

int[,,,] Result1=new int[10,10,10,10]; 
int[,,,] Result2=new int[10,10,10,10]; 
int[,,,] Result3=new int[10,10,10,10]; 
int[,,,] Result4=new int[10,10,10,10]; 

for (int i=0;i<10;i++) 
{ 
    for (int j=0;j<10;j++) 
    { 
    for (int k=0;k<10;k++) 
    { 
     for (int l=0;l<10;l++) 
     { 
     Result1[i,j,k,l]=myFunction1(i,j,k,l); 
     Result2[i,j,k,l]=myFunction2(i,j,k,l); 
     Result3[i,j,k,l]=myFunction3(i,j,k,l); 
     Result4[i,j,k,l]=myFunction4(i,j,k,l); 
     } 
    } 
    } 
} 

Все элементы массива результатов полностью независимы друг от друга. Мой ПК имеет 8 ядер, и я создал поток для каждого из методов myFunction, но все же весь процесс займет много времени, потому что есть много случаев. Мне интересно, есть ли способ запустить это на GPU, а не на процессоре. Я не делал этого раньше, и я не знаю, как он будет работать. Я ценю, если кто-то может мне помочь в этом.

+0

Вы вставляете строки в таблицу? Использование SqL Server? Попробуйте Массовая вставка; вашим узким местом может быть БД, а не программа C#. –

ответ

1

Вы можете рассмотреть возможность перезаписи этой части приложения с помощью C++ AMP и вызвать его из вашего .NET-кода. Для получения дополнительной информации см. http://blogs.msdn.com/b/nativeconcurrency/archive/2012/08/30/learn-c-amp.aspx

Однако в коде, который вы показываете, имеется 40 000 данных, а не 4 000 000.

Есть около 2,6 миллиона секунд в месяц. Для 40 000 данных, что дает вам более минуты за каждый день. (Даже если у вас было 4 миллиона точек данных, все равно было бы намного больше половины секунды для каждой точки данных.) Я не знаю, что делают эти функции, но я был бы удивлен тем, что что-то, что нужно запустить так долго является хорошим кандидатом для работы на графическом процессоре.

Возможно, вам нужно пересмотреть алгоритмы, используемые в этих функциях, чтобы узнать, можно ли их оптимизировать. Возможно, вам даже придется пересмотреть свою идею, чтобы вычислить каждый набор данных независимо от других. Вы уверены, что один результат не может быть более эффективно рассчитан, если вы уже знаете некоторые другие результаты?

UPDATE:

Что я имею в виду последнее замечание, что там может быть повторен расчет происходит. Например, если часть расчетов, выполненных myFunction1 зависит только от первых двух параметров, вы можете перестроить свой код следующим образом:

for (int i = 0; i < 10; i++) 
{ 
    for (int j = 0; j < 10; j++) 
    { 
    var commonPartValue = commonPart(i, j); 

    for (int k = 0; k < 10; k++) 
    { 
     for (int l = 0; l < 10; l++) 
     { 
     Result1[i, j, k, l] = myFunction1b(i, j, k, l, commonPartValue); 
     } 
    } 
    } 
} 

Результирующий эффект будет то, что вы вычислить эту «общую часть» один раз, где вы делали это сто раз.

В другом случае вы можете более эффективно вычислить результат с использованием предыдущего результата, чем если бы вам пришлось делать это с нуля. Например, n2 можно легко вычислить как n * n, но если вы знаете (n - 1) ² уже, чем n² = (n - 1) ² + 2 * n - 1. В целых арифметических это означает, что вы заменяете умножение на сдвиг и декремент, который быстрее.

Теперь я не утверждаю, что ваша проблема так же проста, как эти примеры, но я говорю, что сначала вы должны искать эти виды оптимизации, прежде чем искать лучшие компиляторы или другое оборудование.

Кроме того, в качестве оповещения: Я предполагаю, что вы храните то, что вы рассчитали на диске, а не в массиве в ОЗУ. Я не хотел бы ждать месяц, пока результаты покажут, а затем отключится ...

+0

Код, который я написал выше, является просто упрощенным примером. Функции, которые я использую (myFunctions), довольно сложны, но я написал их наилучшим образом оптимизированным образом. Проблема здесь в том, что число сдвигов не является самими функциями. – Ehsan

+0

Ну, если вы уверены в этом, то посмотрите на C++ AMP. –

1

Да, интуиция для этого сценария заключается в использовании многопоточных/четных графических процессоров для ускорения. Но важно выяснить, подходит ли сценарий для параллельных вычислений.

Как вы предположили, эти наборы данных независимы друг от друга, но при запуске многопоточной версии на 8 ядрах нет очевидного улучшения: это говорит о потенциальных проблемах: либо ваше утверждение о независимости набора данных неверно, либо ваша реализация многопоточного кода не оптимизирована. Я бы посоветовал вам сначала настроить свой код, чтобы увидеть улучшение, а затем искать методы для трансплантации этого в форматы плат GPU.

или вы можете посмотреть на OPENCL, который предназначен как для параллельных нитей, так и для ядер GPU. , но важно выяснить, действительно ли ваш вопрос подходит для параллельных вычислений.

+0

Спасибо за комментарий. Я вижу улучшения, покупающие код на нескольких ядрах. Фактически, запуск кода на 8 ядре увеличивает скорость в 8 раз (поскольку элементы независимы), но учитывая тот факт, что существует так много данных, для создания базы данных все еще требуется много. Мне нужно увеличить скорость в гораздо большем, чем 8. Я изучал CUDA и CUDAfy, но я еще не понял, как это сделать. – Ehsan

0

Я не думаю, что ваш пример кода использует все восемь ядер - только один. После следует использовать все 8:

private void Para() 
    { 
     int[, , ,] Result1 = new int[10, 10, 10, 10]; 
     int[, , ,] Result2 = new int[10, 10, 10, 10]; 
     int[, , ,] Result3 = new int[10, 10, 10, 10]; 
     int[, , ,] Result4 = new int[10, 10, 10, 10]; 

     Parallel.For(0L, 10, i => 
     { 
      Parallel.For(0L, 10, j => 
      { 
       Parallel.For(0L, 10, k => 
       { 
        Parallel.For(0L, 10, l => 
        { 
         Result1[i, j, k, l] = myFunction1(i, j, k, l); 
         Result2[i, j, k, l] = myFunction2(i, j, k, l); 
         Result3[i, j, k, l] = myFunction3(i, j, k, l); 
         Result4[i, j, k, l] = myFunction4(i, j, k, l); 
        }); 
       }); 
      }); 
     }); 
    } 

Если этого недостаточно have a look at Cudafy должен сделать свой живой легче, чем переписывать все свои сложные функции в C++.

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