Search code examples
matlabparallel-processingpsychtoolbox

How can I parallelize input and display in MATLAB?


I'm using Psychtoolbox in MATLAB to run a behavioral psychology paradigm. As part of the paradigm, users have to view a visual stimulus and respond to it using some input mechanism. For a keyboard, this works as follows:

  1. show stimulus
  2. poll keyboard for response
    1. if no response detected, loop back to 1
    2. if response detected, break and move on with script

This works fine for a keyboard, as step 2 takes between 1-2 ms. The problem comes when I use an alternate input mechanism; in that case, step 2 takes ~20 ms. (I need this alternate input to run the study, and that should be considered immutable fact.) As the stimulus changes with a very short timespan, this added delay breaks the task.

My current thought is to try to use the parallel processing, such that one thread shows the stimulus, and another thread polls the keyboard. I'm currently using the Parallel Computing Toolbox to do this. The problem I'm having is that I don't know how to direct keyboard input to a "parallelized" thread. Does anyone know (1) whether it's possible to direct keyboard input to a thread / have a thread send a visual signal to a monitor, and if yes, (2) how to do it?

Also, if anyone has any better ideas as to how to approach this problem, I'm all ears.


Solution

  • According to this MATLAB newsgroup thread, it appears that threads can't modify graphics objects. Only the desktop MATLAB client can do that. This means that you can't handle updating of graphics from a thread, and I can confirm this as I tried it and wasn't able to modify figures or even the root object from a thread.

    However, I think you may be able to do the main graphics updating in MATLAB while a thread handles polling for your input. Here's a sample function for continuously updating a display until a thread waiting for input from KbCheck is finished running:

    function varargout = plot_until_input
    
      obj = createJob();                                   %# Create a job
      task = createTask(obj,@get_input,4,{deviceNumber});  %# Create a task
      submit(obj);                                         %# Submit the job
      waitForState(task,'running');  %# Wait for the task to start running
    
      %# Initialize your stimulus display here
      while ~strcmp(get(task,'State'),'finished')  %# Loop while the task is running
        %# Update your stimulus display here
      end
    
      varargout = get(task,'OutputArguments');  %# Get the outputs from the task
      destroy(obj);                             %# Remove the job from memory
    
    %#---Nested functions below---
    
      function [keyIsDown,secs,keyCode,deltaSecs] = get_input(deviceNumber)
        keyIsDown = false;
        while ~keyIsDown  %# Keep looping until a key is pressed
          [keyIsDown,secs,keyCode,deltaSecs] = KbCheck(deviceNumber);
        end
      end
    
    end
    

    I was able to successfully run the above function with some simple plotting routines and replacing the code in get_input with a simple pause statement and a return value. I'm unsure whether KbCheck will work in a thread, but hopefully you will be able to adapt this for your needs.

    Here's the documentation for the Parallel Computing Toolbox functions used in the above code: createJob, createTask, submit, waitForState, destroy.