是什么让这段代码更快?

时间:2014-05-16 23:52:18

标签: matlab

我正在Matlab中实现1维Bin装箱问题(BPP)的First Fit(FF)启发式算法。

在第一次实现算法之后,我尝试改进我的代码,最后我得到了第二个实现,我认为它更好,因为在我看来它更像是优雅

我的好奇心(让我说我是一个完美主义者)引导我运行并比较两种实现方式。他们到达的结果完全相同(应该是这样),但我的第一次实施速度提高了10倍以上!

我的问题是:你能帮我找到原因吗?第二个实现的哪个部分正在减慢我的代码?

第一次实施:

function packing = firstFit(items)

global N_items bin_size

item_assign = zeros(N_items,1);
residual = bin_size*ones(N_items,1);
tmp = residual;

% Assign each item on the list to a bin
for i = 1:N_items
    j = 1; % always start by trying the first bin
    % Repeat until the item is assigned to a bin
    while true
        if items(i) > residual(j)
            j = j+1; % try to fit it in the next bin 
        else
            residual(j) = residual(j)-items(i);
            item_assign(i) = j;
            break
        end
    end
end

% Check how many bins were needed to accommodate all items
N_bins = N_items - sum(residual == tmp);

packing = cell(N_bins,3);
for i = 1:N_bins
    packing{i,1} = item_assign == i;
    packing{i,2} = items(packing{i,1});
    packing{i,3} = residual(i);
end

end

第二次实施:

function packing = firstFit2(items)

global N_items bin_size

% Initialize 1st bin
packing{1,1} = false(N_items,1);
packing{1,3} = bin_size;
N_bins = 1;

% Assign each item on the list to a bin
for i = 1:N_items
    % Look for the first bin able to hold this item
    j = find(cell2mat(packing(:,3)) >= items(i),1);
    if isempty(j)
        % Create a new empty bin if necessary
        j = N_bins + 1;
        packing{j,1} = false(N_items,1);
        packing{j,3} = bin_size;
        N_bins = j;
    end
    % Assign item to that bin
    packing{j,1}(i) = true;
    packing{j,2} = [packing{j,2};items(i)];
    packing{j,3} = packing{j,3} - items(i);
end

end

结果:

对于给定的数据集,第一次实现时运行时间约为0.011秒,而第二次运行时间约为0.13秒。

如果您愿意,我可以为您提供数据集,请告诉我。

BPP的简要说明:

有一组具有特征长度的物品。这些物品应装入一组固定尺寸的箱子中。目标是使用尽可能少的垃圾箱来包装所有物品。

FF启发式的简要说明:

First-Fit(FF)启发式背后的想法非常简单:

  1. 项目被顺序考虑,并且每个项目都位于可容纳它的第一个bin中。
  2. 用剩余容量R = C初始化箱子,当物品被安排到其中时,剩余容量减少了该物品的大小。
  3. 如果没有任何打开的垃圾箱可以容纳一个项目,则会创建一个新的空垃圾箱。

1 个答案:

答案 0 :(得分:0)

您的代码比它需要的复杂得多。要说一个实现比另一个更快,这并不容易,因为MATLAB在幕后进行了各种优化。循环,特别是在循环内改变向量的大小(正如你在第二个代码中所做的那样)通常很慢。

干净的MATLAB方式看起来像

%% do the actual work
binSize = 20;
itemMaxSize = 10;
numItems = 10;

items = randi(itemMaxSize, numItems, 1);

R = binSize * ones(numItems, 1); % there can not be more bins than items
assignment = zeros(numItems, 1);

for i = 1:numItems
    assignment(i) = find( R >= items(i), 1, 'first');
    R(assignment(i)) = R(assignment(i)) - items(i);

end

R = R( R < binSize );

%% make a figure
figure
hold on
for i = 1:length(R)
    itemInds = find(assignment == i);
    sizes = items(itemInds);

    plot(i, cumsum(sizes), '*')
    text(i * ones(size(sizes)) + .1, cumsum(sizes), num2str(itemInds))
end


ylim([0 round(binSize*1.1)])
plot([.5 length(R)+.5], [binSize binSize], '--')
xlim([.5, length(R)+.5]);
set(gca, 'xtick', 1:length(R))
xlabel('bin ind')
ylabel('fill')