[vtkusers] vtkImageReader much faster than vtkImageReader2??

David Gobbi david.gobbi at gmail.com
Thu Jun 12 13:55:14 EDT 2014


Hi Marco,

Try repeating the tests with SetDataByteOrderToBigEndian().  If the
byte reordering is really the most CPU-intensive part of the read, as
I suspect, then this should reduce both times but perhaps one more
than the other.

Other than that, I don't have any guesses.  In vtkImageReader.cxx, I
notice that it reads into a buffer where it performs the byte swap,
whereas vtkImageReader2.cxx doesn't use a buffer.  If this makes any
difference at all, though, it should be in favor of vtkImageReader2
(unless CPU cache misses are involved).

The only way to be sure is to run the tests in a C++ profiler, on OS X
I use "Instruments" but I've never done profiling on Windows.  On a
related note, one thing that I did find via profiling is that fread()
was 4x faster than doing read() on a C++ fstream.  But this was only
meaningful when reading from disk cache.  When the reads were hitting
the actual disk, the difference was negligible.

  David



On Thu, Jun 12, 2014 at 11:37 AM, Marco Sambin <m.sambin at gmail.com> wrote:
> Hi David,
>
> first of all, thank you for your reply.
> No, the difference is not related to disk caching issues. Here are two test
> methods that I've written:
>
>
> public static void testVTKImageReader()
>   {
>     long startTime = System.currentTimeMillis();
>
>     vtkImageReader testReaderVTK =  new vtkImageReader();
>     testReaderVTK.FileLowerLeftOn();
>     testReaderVTK.SetFileDimensionality(3);
>     testReaderVTK.SetFileName("C:\\Test\\SeriesVolume.raw");
>
>     testReaderVTK.SetDataExtent(0, 511,
>                           0, 511,
>                           0, 520);
>     testReaderVTK.SetDataSpacing(1.0, 1.0, 1.0);
>     testReaderVTK.SetDataOrigin(0.0, 0.0, 0.0);
>     testReaderVTK.SetDataScalarTypeToUnsignedShort();
>     testReaderVTK.SetDataByteOrderToBigEndian();
>     testReaderVTK.UpdateWholeExtent();
>
>     long endTime = System.currentTimeMillis();
>
>     System.out.println("Volume read by vtkImageReader. Total time millis = "
> + (endTime - startTime));
>   }
>
>   public static void testVTKImageReader2()
>   {
>     long startTime = System.currentTimeMillis();
>
>     vtkImageReader2 testReaderVTK =  new vtkImageReader2();
>     testReaderVTK.FileLowerLeftOn();
>     testReaderVTK.SetFileDimensionality(3);
>     testReaderVTK.SetFileName("C:\\Test\\SeriesVolume.raw");
>
>     testReaderVTK.SetDataExtent(0, 511,
>                           0, 511,
>                           0, 520);
>     testReaderVTK.SetDataSpacing(1.0, 1.0, 1.0);
>     testReaderVTK.SetDataOrigin(0.0, 0.0, 0.0);
>     testReaderVTK.SetDataScalarTypeToUnsignedShort();
>     testReaderVTK.SetDataByteOrderToBigEndian();
>     testReaderVTK.UpdateWholeExtent();
>
>     long endTime = System.currentTimeMillis();
>
>     System.out.println("Volume read by vtkImageReader2. Total time millis =
> " + (endTime - startTime));
>   }
>
> After doing a couple of "cold starts" in order to "warm up" disk caches, on
> my test PC method "testVTKImageReader()" executes in around 2 seconds, while
> method "testVTKImageReader2()" executes in around 10 seconds.
> I've tried executing testVTKImageReader() before and testVTKImageReader2()
> after or viceversa during the same execution session, but the result doesn't
> change: testVTKImageReader() is always around 5 times faster than
> testVTKImageReader2().
>
> Can you guess why?
> Thanks and best regards,
>
> Marco Sambin
>
>
>
> On Thu, Jun 12, 2014 at 7:12 PM, David Gobbi <david.gobbi at gmail.com> wrote:
>>
>> Hi Marco,
>>
>> When used the way they are in your example code, vtkImageReader and
>> vtkImageReader2 should be exactly the same speed.
>>
>> Can you explain your testing methodology in more detail?  I suspect that
>> when you tested vtkImageReader2, it was reading from disk, and when
>> testing vtkImageReader, it was reading from disk cache.  The only part
>> of the "read" operation that actually requires any CPU time is the byte
>> swapping, but that should be identical for the two readers.
>>
>>  - David
>>
>>
>> On Thu, Jun 12, 2014 at 11:00 AM, Marco Sambin <m.sambin at gmail.com> wrote:
>> > Hi all.
>> > I am reading a volume made up of a set of "slices" stored in a single
>> > large
>> > raw file, containing just the raw pixels of each slice (unsigned short
>> > values), one slice after the other. I know in advance image size,
>> > position,
>> > orientation and spacing information related to each slice.
>> > I used to read my input raw volume through the vtkImageReader2 class, as
>> > documentation of vtkImageReader states:
>> >
>> > "vtkImageReader provides methods needed to read a region from a file. It
>> > supports both transforms and masks on the input data, but as a result is
>> > more complicated and slower than its parent class vtkImageReader2."
>> >
>> > so I always assumed vtkImageReader2 to be faster than vtkImageReader to
>> > read
>> > a simple volume made up of a set of raw slices.
>> > This until today, when I tried replacing my instance of vtkImageReader2
>> > with
>> > an instance of vtkImageReader. Guess what? My volume reading code now
>> > executes around 10 times faster!
>> >
>> > Is this expected? Can you guess what may be the reason for such a
>> > significant difference in performance between vtkImageReader2 and
>> > vtkImageReader, the latter being much faster in my scenario (despite
>> > what
>> > the documentation states)?
>> >
>> > For completeness, I am using VTK 6.1 64-bit from Java 7 64-bit, under
>> > Windows 7 Professional 64-bit. Here is a code fragment showing how I
>> > configure my reader:
>> >
>> > [...]
>> > imageReaderVTK =  new vtkImageReader(); // much slower if I use
>> > "vtkImageReader2" here
>> > imageReaderVTK.FileLowerLeftOn();
>> > imageReaderVTK.SetFileDimensionality(3);
>> > imageReaderVTK.SetFileName(curRawVolFile.getAbsolutePath());
>> > imageReaderVTK.SetDataExtent(0, sliceCols - 1,
>> >                       0, sliceRows - 1,
>> >                       0, numOfUsedImages - 1);
>> > imageReaderVTK.SetDataSpacing(xSpacing, ySpacing, zSpacing);
>> > imageReaderVTK.SetDataOrigin(0.0, 0.0, 0.0);
>> > imageReaderVTK.SetDataScalarTypeToUnsignedShort();
>> > imageReaderVTK.SetDataByteOrderToBigEndian();
>> > imageReaderVTK.UpdateWholeExtent();
>> > [...]
>> >
>> > My typical input raw volume is made up of around 500 slices, each one
>> > 512x512 pixels large.
>> >
>> > Thanks in advance for your feedback.
>> > Best regards,
>> >
>> > Marco Sambin
>
>


More information about the vtkusers mailing list