Improving efficiency of using tables

4 views (last 30 days)
Tejas
Tejas on 22 May 2021
Answered: Abhas on 19 Feb 2024
A simple working example of my code is given below.
% Initialization
num = 10; time_limit = 10000;
agent = array2table(zeros(num,4),'VariableNames',{'loc','prev_loc','loc_time','collected'});
env = randi(10,10,10); env(1,1) = 0;
agent.loc = ones(num,1);
% Collect rewards one-by-one
agent.loc_time = ones(num,1);
tic
for t = 1:time_limit
for i = 1:num
% If agent i has reached a position at time t
if agent.loc_time(i) == t
% If there is a reward at agent's location
if env(agent.loc(i)) > 0
[agent(i,:),env] = return_with_reward(agent(i,:),env);
% Otherwise
else
[agent(i,:),env] = find_reward(agent(i,:),env);
end
end
end
end
toc
function [agent,env] = find_reward(agent,env)
agent.prev_loc = agent.loc;
% Select a location to go randomly
agent.loc = randi([2,length(env(:))],1);
% Find time to get there
agent.loc_time = agent.loc_time + abs(agent.loc - agent.prev_loc);
end
function [agent,env] = return_with_reward(agent,env)
loc = agent.loc;
% Update environment
env(loc) = max(0, env(loc) - 1);
agent.collected = agent.collected + 1;
agent.prev_loc = loc;
% Return to starting position
agent.loc = 1;
% Find time to reach
agent.loc_time = agent.loc_time + abs(agent.loc - agent.prev_loc);
end
In this, the agents start at position (1,1), go to random positions till they get a reward, return with that reward to (1,1), and go again. For 10 agents and 10k time steps, this takes about 2 seconds. I'm new to table-oriented programming, so I'm wondering if there are ways I can improve the efficiency of this process.

Answers (1)

Abhas
Abhas on 19 Feb 2024
Hi Tejas,
We can optimize the code by improving the following key factors:
  1. Precomputing Random Locations: All random locations are generated before the loop, reducing runtime overhead.
  2. Vectorized Logical Indexing: Agents are processed in batches using logical indexing, which is faster than iterative loops.
  3. Batch Updating: Agents that found a reward and those that did not are updated in separate batches, leveraging MATLAB's efficient handling of array operations.
  4. Direct Assignment: The starting position for agents returning with a reward is assigned in one operation, rather than in a loop.
The optimized MATLAB code is as follows:
% Initialization
num = 10; time_limit = 10000;
agent = array2table(zeros(num,4),'VariableNames',{'loc','prev_loc','loc_time','collected'});
env = randi(10,10,10); env(1,1) = 0;
agent.loc = ones(num,1);
% Collect rewards one-by-one
agent.loc_time = ones(num,1);
tic
% Precompute random locations
random_locs = randi([2, numel(env)], num, time_limit);
for t = 1:time_limit
% Find agents that have reached their position at time t
active_agents_idx = find(agent.loc_time == t);
% Check for rewards at the agents' locations
rewards_available = env(agent.loc(active_agents_idx)) > 0;
% Update agents that found a reward
agents_with_reward_idx = active_agents_idx(rewards_available);
% Update agents that did not find a reward
agents_without_reward_idx = active_agents_idx(~rewards_available);
if ~isempty(agents_with_reward_idx)
[agent(agents_with_reward_idx,:), env] = return_with_reward(agent(agents_with_reward_idx,:), env);
end
if ~isempty(agents_without_reward_idx)
[agent(agents_without_reward_idx,:), env] = find_reward(agent(agents_without_reward_idx,:), env, random_locs(agents_without_reward_idx, t));
end
end
toc
Elapsed time is 0.497633 seconds.
function [agent,env] = find_reward(agent,env, random_locs)
agent.prev_loc = agent.loc;
% Use precomputed random locations
agent.loc = random_locs;
% Find time to get there
agent.loc_time = agent.loc_time + abs(agent.loc - agent.prev_loc);
end
function [agent,env] = return_with_reward(agent,env)
locs = agent.loc;
% Vectorized update to environment and agent properties
for loc = locs'
env(loc) = max(0, env(loc) - 1);
end
agent.collected = agent.collected + 1;
agent.prev_loc = locs;
% Return to starting position
agent.loc = ones(size(agent.loc)); % Assign an array of ones
% Find time to reach
agent.loc_time = agent.loc_time + abs(agent.loc - agent.prev_loc);
end
The optimized code runs 5 times faster than the original code by using the above methods.
You may refer to the following documentation links to have a better understanding on vectorization and precomputing arrays:
  1. https://www.mathworks.com/help/matlab/matlab_prog/preallocating-arrays.html
  2. https://www.mathworks.com/help/matlab/matlab_prog/vectorization.html

Categories

Find more on Linear Algebra in Help Center and File Exchange

Products


Release

R2020a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!