Идеи для GPU реализации коэффициента Хеффдинга "D" (Зависимость)? - PullRequest
4 голосов
/ 14 февраля 2012

Я пытаюсь придумать очень быстрый алгоритм для расчета этой очень интересной статистики, которая в полной мере использует возможности мощного графического процессора.В идеале я буду делать это в Matlab, используя Jacket, но другие идеи в коде CUDA или OpenCL также будут высоко оценены.По сути, я хочу собрать множество умных идей, которые я могу попытаться объединить, а затем я попытаюсь открыть результат, чтобы другие могли его использовать.

Несмотря на силу этого коэффициента зависимости(он способен обнаруживать даже отношения зависимости «один ко многим»), в нем почти ничего нет, за исключением двух источников: статистического программного обеспечения SAS и превосходного пакета R Hmisc от Фрэнка Харрелла.Вы можете прочитать описание алгоритма здесь:

http://support.sas.com/documentation/cdl/en/procstat/63104/HTML/default/viewer.htm#procstat_corr_sect016.htm

А вот код Харрелла на Фортране (который удивительно легко выполнить, если вы уже поняли вычисление):

http://hmisc.sourcearchive.com/documentation/3.7-0/hoeffd_8f-source.html

(также на странице 128 pdf-документации для Hmisc есть некоторые подробности.)

Это очень требовательный к вычислениям алгоритм - если вы хотите применить егок набору данных, который состоит из тысяч строк и нескольких тысяч столбцов, даже с быстрой реализацией на Фортране, вы будете ждать результата много дней - даже на новой машине.Я надеюсь, что использование карты уровня Nvidia GTX 580, или, что еще лучше, Tesla, снизит это до пары часов.В этом случае комбинация будет аналитической силой, с которой нужно считаться, будь то идентификация генов или обнаружение корреляций в экспериментальных данных.

В любом случае, я с нетерпением жду откликов людей и надеюсь, что мы сможем сделать быстрый GPUНа основе алгоритма Хеффдинга D реальность.

Заранее благодарим за любые идеи - и, пожалуйста, не стесняйтесь, дайте частичные или недоделанные идеи!

Обновление: Итак, Яша щедро предоставил работающую реализацию D Хоффдинга вMatlab, который выполнил одну из моих целей.Другим было радикальное повышение скорости с помощью графического процессора, предпочтительно с помощью Jacket.Кто-нибудь видит путь или стратегию, чтобы сделать это умным способом на GPU?

Ответы [ 2 ]

2 голосов
/ 16 февраля 2012

Я хотел, чтобы это был просто комментарий, но он слишком длинный.Не беспокойтесь, если вы не хотите принять его как ответ или что-то еще.

Во-первых, похвально, что вы думаете о том, как сопоставить это с GPU.Многие другие ученые должны уделить время, чтобы рассмотреть подобные идеи для своих алгоритмов.Однако после прочтения описания я не убежден, что графический процессор является идеальным способом распараллеливания этого конкретного метода.Причина, по которой я это говорю, заключается в том, что программирование на GP-GPU имеет тенденцию быть очень эффективным при «пакетной обработке», то есть алгоритмах, которые естественным образом поддаются элементарной базовой манипуляции (уровень потока).

Это не такПонятно, что есть полезное разделение этого алгоритма по этим направлениям, за исключением уровня суммирования / вычисления ранга, о котором уже упоминали другие (и такого рода подфункции уже хорошо поняты в GPU).Но если вы уменьшите масштаб и начнете пытаться подумать о том, как вы можете использовать графический процессор для ускорения работы на уровне сравнения столбцов, вы мало что сможете сделать.Знание мест, где конкретные записи меньше значения данной точки, не позволит вам избежать тех же вычислений при изменении одного или другого столбца.

Короче говоря, вам придетсяВыполните N(N+1)/2 различные итерации алгоритма на верхнем уровне, и избежать этого невозможно.В каждом из этих алгоритмов достаточно места для отправки массивов столбцов в графический процессор и проведения сравнений на уровне потоков для быстрого расчета статистики различных рангов.

Лучшим подходом может быть использование MPI в многопроцессорном режиме.настройки, так что вы выполняете каждую высокоуровневую итерацию для разных процессоров.Параллельная модель master-slave (со страшным названием) кажется подходящей, если у вас недостаточно процессоров и / или если вы хотите, чтобы каждый процессор использовал GPU в одной высокоуровневой итерации.Пока вы продолжаете вычислять верхне-треугольные элементы матрицы «ковариации» Хоффдинга, вы продолжаете выкачивать задачи на доступные процессоры.

Во-вторых, я думаю, что Matlab и Jacketздесь больше проблем со временем, чем вы можете себе представить.Да, Matlab оптимизирован для некоторых операций линейной алгебры, но почти всегда он однозначно медленнее, чем любой «настоящий» язык программирования.Компромисс состоит в том, что вы получаете множество удобных функций с документацией коммерческого уровня, и это иногда полезно.

Альтернатива, которую я предлагаю вам, - это использовать PyCUDA вместе с mpi4py на языке программирования Python.С NumPy и Cython , Python строго лучше и быстрее, чем Matlab, даже с точки зрения удобных функций и простоты использования.Если вы используете плагин PyDev для IDE Eclipse , даже пользовательский интерфейс терминала Matlab в основном идентичен.Кроме того, вам не нужно платить за лицензию или какую-либо дополнительную плату за Jacket.

Вам нужно будет немного поработать, чтобы PyCUDA и mpi4py работали вместе, но в конце я думаю, чтоopen-source-ness сделает ваши усилия гораздо более ценными для большего числа людей, и код, вероятно, будет намного быстрее.

Кроме того, если вы действительно придерживаетесь Matlab, вы рассчитали время для существующего Fortran?код в случае одной пары столбцов, для тысяч записей, но только в двух столбцах?Если это достаточно быстро, вы сможете написать обертку для этого Fortran с помощью mex-файла.И в этом случае простые многопроцессорные сессии Matlab могут быть всем, что вам нужно.

1 голос
/ 17 февраля 2012

Ниже приведен пример кода с простой реализацией меры зависимости Хоффдинга D в MATLAB. Это НЕ графический процессор, но может оказаться полезным для людей, которые хотят рассчитать эту статистику и не используют Fortran, или в качестве отправной точки для ее размещения на GPU. (Расширенный заголовок иллюстрирует значения D Хоффдинга для нескольких типов совместных распределений.)

function [ D ] = hoeffdingsD( x, y )
%Compute's Hoeffding's D measure of dependence between x and y
%   inputs x and y are both N x 1 arrays
%   output D is a scalar
%     The formula for Hoeffding's D is taken from
%     http://support.sas.com/documentation/cdl/en/procstat/63104/HTML/default/viewer.htm#procstat_corr_sect016.htm
% Below is demonstration code for several types of dependencies.
%
% % this case should be 0 - there are no dependencies
% x = randn(1000,1);
% y = randn(1000,1);
% D = hoeffdingsD( x, y );
% desc = 'x = N( 0, 1 ), y and x independent';
% desc = sprintf( '%s, Hoeffding''s D = %f', desc, D );
% fprintf( '%s\n', desc );
% figure; plot(x,y,'.'); title( desc );
% 
% % the rest of these cases have dependencies of different types
% x = randn(1000,1);
% y = x;
% D = hoeffdingsD( x, y );
% desc = 'x = N( 0, 1 ), y = x';
% desc = sprintf( '%s, Hoeffding''s D = %f', desc, D );
% fprintf( '%s\n', desc );
% figure; plot(x,y,'.'); title( desc );
% 
% x = randn(1000,1);
% y = cos(10*x);
% D = hoeffdingsD( x, y );
% desc = 'x = N( 0, 1 ), y = cos(10x)';
% desc = sprintf( '%s, Hoeffding''s D = %f', desc, D );
% fprintf( '%s\n', desc );
% figure; plot(x,y,'.'); title( desc );
% 
% x = randn(1000,1);
% y = x.^2;
% D = hoeffdingsD( x, y );
% desc = 'x = N( 0, 1 ), y = x^2';
% desc = sprintf( '%s, Hoeffding''s D = %f', desc, D );
% fprintf( '%s\n', desc );
% figure; plot(x,y,'.'); title( desc );
% 
% x = randn(1000,1);
% y = x.^2 + randn(1000,1);
% D = hoeffdingsD( x, y );
% desc = 'x = N( 0, 1 ), y = x^2 + N( 0, 1 )';
% desc = sprintf( '%s, Hoeffding''s D = %f', desc, D );
% fprintf( '%s\n', desc );
% figure; plot(x,y,'.'); title( desc );
% 
% x = rand(1000,1);
% y = rand(1000,1);
% z = sign(randn(1000,1));
% x = z.*x; y = z.*y;
% D = hoeffdingsD( x, y );
% desc = 'x = z U( [0, 1) ), y = z U( [0, 1) ), z = U( {-1,1} )';
% desc = sprintf( '%s, Hoeffding''s D = %f', desc, D );
% fprintf( '%s\n', desc );
% figure; plot(x,y,'.'); title( desc );
% 
% x = rand(1000,1);
% y = rand(1000,1);
% z = sign(randn(1000,1));
% x = z.*x; y = -z.*y;
% D = hoeffdingsD( x, y );
% desc = 'x = z U( [0, 1) ), y = -z U( [0, 1) ), z = U( {-1,1} )';
% desc = sprintf( '%s, Hoeffding''s D = %f', desc, D );
% fprintf( '%s\n', desc );
% figure; plot(x,y,'.'); title( desc );

N = size(x,1);

R = tiedrank( x );
S = tiedrank( y );

Q = zeros(N,1);
parfor i = 1:N
    Q(i) = 1 + sum( R < R(i) & S < S(i) );
    % and deal with cases where one or both values are ties, which contribute less
    Q(i) = Q(i) + 1/4 * (sum( R == R(i) & S == S(i) ) - 1); % both indices tie.  -1 because we know point i matches
    Q(i) = Q(i) + 1/2 * sum( R == R(i) & S < S(i) ); % one index ties.
    Q(i) = Q(i) + 1/2 * sum( R < R(i) & S == S(i) ); % one index ties.
end

D1 = sum( (Q-1).*(Q-2) );
D2 = sum( (R-1).*(R-2).*(S-1).*(S-2) );
D3 = sum( (R-2).*(S-2).*(Q-1) );

D = 30*((N-2)*(N-3)*D1 + D2 - 2*(N-2)*D3) / (N*(N-1)*(N-2)*(N-3)*(N-4));

end
...