【问题标题】:Speedup constrained shuffling. GPU (Tesla K40m), CPU parallel computations in MATLAB加速约束洗牌。 GPU (Tesla K40m),MATLAB 中的 CPU 并行计算
【发布时间】:2018-05-14 04:26:29
【问题描述】:

我有 100 盏灯。他们在眨眼。我观察了一段时间。对于每盏灯,我计算闪烁间隔的平均值、标准差和自相关。 现在我应该重新采样观察到的数据并保持排列,其中所有参数(平均值、标准差、自相关)都在某个范围内。我拥有的代码效果很好。但是每轮实验需要很长时间(一周)。我是在 12 核 2 Tesla K40m GPU 的计算服务器上做的(详情在最后)。

我的代码:

close all
clear all
clc
% open parpool skip error if it was opened
try parpool(24); end

% Sample input. It is faked, just for demo.
% Number of "lamps" and number of "blinks" are similar to real.
NLamps = 10^2;
NBlinks = 2*10^2;
Events = cumsum([randg(9,NLamps,NBlinks)],2); % each row - different "lamp"
DurationOfExperiment=Events(:,end).*1.01;

%% MAIN
% Define parameters
nLags=2; % I need to keep autocorrelation with lags 1-2
alpha=[0.01,0.1]; % range of allowed relative deviation from observed 
                  % parameters should be > 0 to avoid generating original
                  % sequence
nPermutations=10^2; % In original code 10^5                  

% Processing of experimental data                  
DurationOfExperiment=num2cell(DurationOfExperiment);
Events=num2cell(Events,2);
Intervals=cellfun(@(x) diff(x),Events,'UniformOutput',false);
observedParams=cellfun(@(x) fGetParameters(x,nLags),Intervals,'UniformOutput',false);
observedParams=cell2mat(observedParams);

% Constrained shuffling. EXPENSIVE PART!!!
while true
    parfor iPermutation=1:nPermutations
        % Shuffle intervals
        shuffledIntervals=cellfun(@(x,y) fPermute(x,y),Intervals,DurationOfExperiment,'UniformOutput',false); 
        % get parameters of shuffled intervals
        shuffledParameters=cellfun(@(x) fGetParameters(x,nLags),shuffledIntervals,'UniformOutput',false);
        shuffledParameters=cell2mat(shuffledParameters);
        % get relative deviation
        delta=abs((shuffledParameters-observedParams)./observedParams);
        % find shuffled Lamps, which are inside alpha range
        MaximumDeviation=max(delta,[] ,2);
        MinimumDeviation=min(delta,[] ,2);
        LampID=find(and(MaximumDeviation<alpha(2),MinimumDeviation>alpha(1)));
        % if shuffling of ANY lamp was succesful, save these Intervals
        if ~isempty(LampID)
            shuffledIntervals=shuffledIntervals(LampID);
            shuffledParameters=shuffledParameters(LampID,:);
            parsave( LampID,shuffledIntervals,shuffledParameters);
            'DONE'
        end
    end
end



%% FUNCTIONS
function [ params ] = fGetParameters( intervals,nLags )
% Calculate [mean,std,autocorrelations with lags from 1 to nLags
    R=nan(1,nLags);
    for lag=1:nLags
            R(lag) = corr(intervals(1:end-lag)',intervals((1+lag):end)','type','Spearman');
    end
    params = [mean(intervals),std(intervals),R];
end
%--------------------------------------------------------------------------
function [ Intervals ] = fPermute( Intervals,Duration )
    % Create long shuffled time-series
    Time=cumsum([0,datasample(Intervals,numel(Intervals)*3)]);
    % Keep the same duration
    Time(Time>Duration)=[];
    % Calculate Intervals
    Intervals=diff(Time);
end
%--------------------------------------------------------------------------
function parsave( LampID,Intervals,params)
    save([num2str(randi(10^9)),'.mat'],'LampID','Intervals','params')
end

服务器规格:

>>gpuDevice() 
CUDADevice with properties:

                      Name: 'Tesla K40m'
                     Index: 1
         ComputeCapability: '3.5'
            SupportsDouble: 1
             DriverVersion: 8
            ToolkitVersion: 8
        MaxThreadsPerBlock: 1024
          MaxShmemPerBlock: 49152
        MaxThreadBlockSize: [1024 1024 64]
               MaxGridSize: [2.1475e+09 65535 65535]
                 SIMDWidth: 32
               TotalMemory: 1.1979e+10
           AvailableMemory: 1.1846e+10
       MultiprocessorCount: 15
              ClockRateKHz: 745000
               ComputeMode: 'Default'
      GPUOverlapsTransfers: 1
    KernelExecutionTimeout: 0
          CanMapHostMemory: 1
           DeviceSupported: 1
            DeviceSelected: 1
>> feature('numcores')
MATLAB detected: 12 physical cores.
MATLAB detected: 24 logical cores.
MATLAB was assigned: 24 logical cores by the OS.
MATLAB is using: 12 logical cores.
MATLAB is not using all logical cores because hyper-threading is enabled.

>> system('for /f "tokens=2 delims==" %A in (''wmic cpu get name /value'') do @(echo %A)')
Intel(R) Xeon(R) CPU E5-2630 v2 @ 2.60GHz  
Intel(R) Xeon(R) CPU E5-2630 v2 @ 2.60GHz  

>> memory
Maximum possible array:               496890 MB (5.210e+11 bytes) *
Memory available for all arrays:      496890 MB (5.210e+11 bytes) *
Memory used by MATLAB:                 18534 MB (1.943e+10 bytes)
Physical Memory (RAM):                262109 MB (2.748e+11 bytes)

*  Limited by System Memory (physical + swap file) available.

问题:

是否有可能加快我的计算速度?我想到了 CPU+GPU 计算,但我不明白如何去做(我没有使用 gpuArrays 的经验)。此外,我不确定这是一个好主意。有时一些算法优化会带来更大的利润,然后是并行计算。

附言 保存步骤不是瓶颈 - 在最好的情况下它会在 10-30 分钟内发生一次。

【问题讨论】:

  • 您是否分析了您的代码(在数据子集上)-> 以准确查看(哪一行)花费的时间?在没有数据和/或一些分析器统计信息的情况下,很难真正说出如何提供帮助 - 但是要考虑的一件事是,简单的 for 循环通常比 cellfun 快(尽管我怀疑它会减少数量级时间......)
  • 我只是使用分析器,将 parfor 替换为 just for。我发现了几点,但它们并不是那么重要。问题是如何并行化进程,并且可以使用 GPU。

标签: matlab performance parallel-processing shuffle gpu


【解决方案1】:

基于 GPU 的处理仅适用于某些功能并使用正确的卡(如果我没记错的话)。

对于您问题的 GPU 部分,MATLAB 有一个 list of available functions - 您可以在 GPU 上运行 - 您的代码中最昂贵的部分是函数 corr 不幸的是,它不在列表中。

如果分析器没有突出瓶颈 - 发生了一些奇怪的事情......所以我对上面的代码进行了一些测试:

nPermutations = 10^0 iteration takes     ~0.13 seconds
nPermutations = 10^1 iteration takes     ~1.3  seconds
nPermutations = 10^3 iteration takes   ~130    seconds
nPermutations = 10^4  probably takes  ~1300    seconds
nPermutations = 10^5  probably takes ~13000    seconds

这还不到一周……

我有没有提到我在您的 while 语句中添加了一个 break - 因为我在您的代码中看不到您曾经“中断”的地方退出 while 循环 - 我希望这不是你的函数永远运行的原因......

while true
    parfor iPermutation=1:nPermutations
        % Shuffle intervals
        shuffledIntervals=cellfun(@(x,y) fPermute(x,y),Intervals,DurationOfExperiment,'UniformOutput',false); 
        % get parameters of shuffled intervals
        shuffledParameters=cellfun(@(x) fGetParameters(x,nLags),shuffledIntervals,'UniformOutput',false);
        shuffledParameters=cell2mat(shuffledParameters);
        % get relative deviation
        delta=abs((shuffledParameters-observedParams)./observedParams);
        % find shuffled Lamps, which are inside alpha range
        MaximumDeviation=max(delta,[] ,2);
        MinimumDeviation=min(delta,[] ,2);
        LampID=find(and(MaximumDeviation<alpha(2),MinimumDeviation>alpha(1)));
        % if shuffling of ANY lamp was succesful, save these Intervals
        if ~isempty(LampID)
            shuffledIntervals=shuffledIntervals(LampID);
            shuffledParameters=shuffledParameters(LampID,:);
            parsave( LampID,shuffledIntervals,shuffledParameters);
            'DONE'
        end
    end
    break    % You need to break out of the loop at some point
             % otherwise it would run forever....
end

【讨论】:

  • 感谢您编辑代码! 1)我有条件中断,2)我只提供样本数据,在现实生活中我需要超过 10^9 次排列才能成功洗牌。
  • 您的问题中没有该信息 - 我只能提供有关您提供的信息的信息。对于 10^9 排列 - 您将获得的每一点性能改进 -> 您将获得 10^9 倍。
猜你喜欢
  • 2015-04-14
  • 1970-01-01
  • 1970-01-01
  • 2019-06-15
  • 2016-05-10
  • 2016-12-06
  • 2018-07-13
  • 2015-08-21
  • 2020-06-03
相关资源
最近更新 更多