Skip to content

Commit

Permalink
Re #1786 Changes from review.
Browse files Browse the repository at this point in the history
  • Loading branch information
abuts committed Feb 14, 2025
1 parent f40790b commit 1a09f88
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 47 deletions.
6 changes: 6 additions & 0 deletions _test/test_config/test_hpc_config.m
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ function test_get_free_memory_from_empty(obj)
break
catch
ok = false;
% wait for short period of time to allow other instance
% of the test job releave its memory
if obj.n_attempts>1; pause(1); end
end
end
Expand All @@ -71,6 +73,8 @@ function test_get_free_memory(obj)
break
catch
ok = false;
% wait for short period of time to allow other instance
% of the test job releave its memory
if obj.n_attempts>1; pause(1); end
end
end
Expand All @@ -93,6 +97,8 @@ function test_mem_works(obj)
break
catch
ok = false;
% wait for short period of time to allow other instance
% of the test job releave its memory
if obj.n_attempts>1; pause(1); end
end
end
Expand Down
83 changes: 51 additions & 32 deletions _test/test_utilities_herbert/fast_map_vs_map_performance.m
Original file line number Diff line number Diff line change
@@ -1,87 +1,106 @@
% script to compare performance of custom fast_map class and
% with performance of standard MATLAB map class.
%
% Run to estimate the price of using MATLAB map wrt custom fast_map
% class
%

% generate specified number of random keys in the range
% exceeding number of keys by 10. This approximate runids obtained from
% two independent experiments provided in two cycles which are not too far
% from each other in time.
n_keys = 200;
base_key = 10+round(rand(1,10*n_keys)*(10*n_keys-1));
base_key = unique(base_key);
base_key = 10+round(rand(1,10*n_keys)*(10*n_keys-1)); %generate 10 times
% more keys then necessary to ensure sufficient unique keys pool.
base_key = unique(base_key); % ensure absence of duplicated keys

n_keys = min(n_keys,numel(base_key));
base_key = base_key(1:n_keys); % leave the expected number of keys
keysUint = uint32(base_key); % convert them into requested type.
mm = min_max(keysUint) % display range of keys used in tests

base_key = base_key(1:n_keys);
keysUint = uint32(base_key);
mm = min_max(keysUint)

n_operations= 40000;

n_operations= 40000; % specify the number of operations to perfrom over maps
% to estimate performance

% prepare test arrays with swarms of test keys to estimate performance
test_keys = repmat(base_key,1,n_operations);
n_idx = n_keys*n_operations;
rnd_idx = randperm(n_idx);
test_keys= test_keys(rnd_idx);



map_stor1 = containers.Map('KeyType',class(keysUint),'ValueType','double');
rnd_idx = randperm(n_idx); % mix keys to ensure we retrieve their
test_keys= test_keys(rnd_idx); % values randomly


% check presence and add values
map_stor = containers.Map('KeyType',class(keysUint),'ValueType','double');

% Measure the time and estimate the performance for different operations
% with maps
%
%
% Measure access/insertion time for MATLAB map
tv = tic;
for i=1:n_idx
[idx1,map_stor1] = add_to_map(map_stor1,test_keys(i));
is = map_stor.isKey(test_keys(i));
if is
idx = map_stor(test_keys(i));
else
idx = map_stor.length;
map_stor(test_keys(i)) = idx+1;
end

end
tv = toc(tv);
fprintf('Find & Add keys to UINT map takes %gsec\n',tv)

% Measure access/insertion time for fast_map map
fm = fast_map();
tv = tic;
for i=1:n_idx
if fm.isKey(test_keys(i))
idx1 = fm.get(test_keys(i));
else
fm = fm.add(test_keys(i),i);
idx = fm.n_members;
fm = fm.add(test_keys(i),idx+1);
end
end
tv = toc(tv);
fprintf('Find & Add keys FAST MAP map takes %gsec\n',tv)

% Measure access time for MATLAB map
tv = tic;
for i=1:n_idx
idx1 = map_stor1(test_keys(i));
idx1 = map_stor(test_keys(i));
end
tv = toc(tv);
fprintf('Find keys in UINT map takes %gsec\n',tv)

% Measure access time for fast_map
tv = tic;
for i=1:n_idx
idx1 = fm.get(test_keys(i));
end
tv = toc(tv);
fprintf('Find keys in FAST MAP map takes %gsec\n',tv)

% Measure access time for fast_map using remapper method for all keys
tv = tic;
fm.optimized = false;
idx1 = fm.get_values_for_keys(test_keys);
tv = toc(tv);
fprintf('Find all keys in FAST MAP non-opt takes %gsec\n',tv)


% Measure access time for optimized fast_map
fm.optimized = true;
tv = tic;
for i=1:n_idx
idx1 = fm.get(test_keys(i));
end
tv = toc(tv);
fprintf('Find keys in FAST MAP opt map takes %gsec\n',tv)
fm = fast_map(test_keys,1:numel(test_keys));

% Measure access time for optimized fast_map using remapper method for all keys
fm = fast_map(base_key,1:numel(base_key));
fm.optimized = true;
tv = tic;
idx1 = fm.get_values_for_keys(test_keys,true);
tv = toc(tv);
fprintf('Find all keys in FAST MAP opt map takes %gsec\n',tv)



function [idx,map] = add_to_map(map,value)
is = map.isKey(value);
if is
idx = map(value);
else
idx = map.length;
map(value) = idx+1;
end
end

36 changes: 27 additions & 9 deletions _test/test_utilities_herbert/ismember_vs_map_performance.m
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
n_keys = 100;
n_operations= 10000;
base_val = rand(1,n_keys);

% script to compare performance of MATLAB map classes with different type
% of keys and usual key-value arrays or cellarray and search operations over
% these arrays or cellarrays
%
% Run to estimate the price of using MATLAB map wrt to different other
% methods of retrieveing values corresponding to set of keys

n_keys = 100; % number of keys to search
n_operations= 10000; % number of operations to run to evaluate performance
base_val = rand(1,n_keys); % generate random double keys

% prepare arrays to test for access speed.
test_val = repmat(base_val,1,n_operations);
n_idx = n_keys*n_operations;
rnd_idx = randperm(n_idx);
test_val= test_val(rnd_idx);

% generate different types of inputkeys
keysUint = uint32(round(base_val*(2^32-1)));
keysChar = arrayfun(@(x)char(typecast(x,'uint8')),keysUint,'UniformOutput',false);
val = 1:100;
val = 1:n_keys;

test_valU = uint32(round(test_val*(2^32-1)));
test_valD = round(test_val*(2^32-1));
test_valC = arrayfun(@(x)char(typecast(x,'uint8')),test_val,'UniformOutput',false);

% build MATLAB maps with different type of keys
map_stor1 = containers.Map('KeyType',class(keysUint),'ValueType',class(val));
map_stor2 = containers.Map('KeyType',class(test_valC{1}),'ValueType',class(val));
map_stor3 = containers.Map('KeyType',class(test_valD),'ValueType',class(val));
Expand All @@ -23,51 +33,54 @@
arr_stor2 = [];

% check presence and add values

% search in MATLAB map with UINT keys
tv = tic;
for i=1:n_idx
[idx1,map_stor1] = find_in_map(map_stor1,test_valU(i));
end
tv = toc(tv);
fprintf('Find & Add keys to UINT map takes %gsec\n',tv)

% search in MATLAB map with CHAR keys
tv = tic;
for i=1:n_idx
[idx2,map_stor2] = find_in_map(map_stor2,test_valC{i});
end
tv = toc(tv);
fprintf('Find & Add keys to CHAR map takes %gsec\n',tv)

% search in cellarray containing char keys
tv = tic;
for i=1:n_idx
[idx3,cell_store] = find_in_cell(cell_store,test_valC{i});
end
tv = toc(tv);
fprintf('Find & Add keys to CELL array takes %gsec\n',tv)

% search in MATLAB map with DOUBLE keys
tv = tic;
for i=1:n_idx
[idx4,map_stor3] = find_in_map(map_stor3,test_valD(i));
end
tv = toc(tv);
fprintf('Find & Add keys to DOUBLE map takes %gsec\n',tv)

% search in array containing double keys
tv = tic;
for i=1:n_idx
[idx5,arr_stor] = find_in_arr(arr_stor,test_valU(i));
end
tv = toc(tv);
fprintf('Find & Add keys to UINT array takes %gsec\n',tv)

% search in array containing double keys if the array is sorted first
tv = tic;
for i=1:n_idx
[idx5,arr_stor2] = find_in_arr_sort(arr_stor2,test_valU(i));
end
tv = toc(tv);
fprintf('Find & Add keys to UINT SORTED array takes %gsec\n',tv)




fprintf('%d\n',idx3);
% % speed of accessing keys without addition
% tic
Expand All @@ -89,6 +102,7 @@


function [idx,map] = find_in_map(map,value)
% find/insert values in MATLAB MAP
is = map.isKey(value);
if is
idx = map(value);
Expand All @@ -99,21 +113,25 @@
end

function [idx,hash_cell] = find_in_cell(hash_cell,value)
% find values in cell array
[in,idx] = ismember(value,hash_cell);
if ~in
idx = numel(hash_cell)+1;
hash_cell{idx} = value;
end
end
function [idx,arr] = find_in_arr(arr,value)
% find values in double array
present = arr == value;
idx = find(present,1);
if isempty(idx)
idx = numel(arr)+1;
arr = [arr,value];
end
end
%
function [idx,arr] = find_in_arr_sort(arr,value)
% find values in double sorted array
arr = sort(arr);
present = arr == value;
idx = find(present,1);
Expand Down
18 changes: 12 additions & 6 deletions herbert_core/utilities/classes/@fast_map/fast_map.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,23 @@
% to compare speed and optimize fast_map operations.
%
properties
% map optimization for doing fast access limit
% property describes the maximal grows limit for key-value
% optimization array.
%
% The map optimization works by allocating large continuous array
% with places for keys as indices. Where keys correspond places in
% array, result contains values, and where no keys present, array
% contains nan-s. The property below shows how much more elements
% The optimization works by allocating large contiguous array
% (opt_array). The indices of this array (idx) are treated as keys
% for values stored in the array, i.e. idx = key-min(keys)+1; so that
% value1 for key1 is calculated as value1 =opt_array(key1-min(keys)+1)
% The elements of opt_array array whith indices not equal to keys
% contain NaN-s.
% The property below shows how much more elements
% the optimization array should contain wrt the number of keys in
% the map. E.g. if empty_space_optimization_limit == 5 and there
% are 100 keys, optimization array would contain no more than 500
% elements. If this ratio is not satisfied, i.e.
% if max(keys)-min(keys) > number_of_keys*empty_space_optimization_limit,
% if
% max(keys)-min(keys) > number_of_keys*empty_space_optimization_limit,
%
% map optimization gets disabled and correspondence between keys
% and values is calculated by binary search.
empty_space_optimization_limit = 5;
Expand Down

0 comments on commit 1a09f88

Please sign in to comment.