Jump to content

Steve Maughan

Members
  • Content Count

    135
  • Joined

  • Last visited

Posts posted by Steve Maughan


  1. I'm considering ways of speeding up an algorithm. One option is to add parallel "for loops". I can certainly add a single parallel "for loop" and get a speedup. The algorithms effectively has nested "for loops" and I could also make the inner "for loops" parallel. Is this a advisable or are nested parallel "for loops" a big no-no? Or does it depend on the number of levels of nesting e.g. one inner parallel loop may be ok, but more would be bad?

     

    Thanks,

     

    Steve


  2. On 6/24/2019 at 8:11 AM, Stefan Glienke said:

    No way - a priority queue that balances when any value changes takes way more work than n-1 comparisons

     

    I am pretty sure that nothing beats the following code performance nor simplicity wise:

    
    for i := Low(data) to High(data) do
    begin
      // update data[i]
      if (i = 0) or (data[i] < min) then
        min := data[i];
    end;

     

    HI Stefan,

     

    You may well be right. I need to test.

     

    Thanks,

     

    Steve


  3. I have a small list of 200 items. Each item has a value. Over time, and with every iteration of my algorithm, each item's value is changed, but only slightly (e.g. ±2%). At any given time I'd like to quickly know the item with the smallest value (I don't care about any other value). What's the best data structure to accomplish this is a speedy manner?

     

    I initially thought of a priority queue, but I'm changing the value of each item in the list.

     

    Thanks,

     

    Steve


  4. I think I've solved it by using a TThreadList object as pseudo stack (FooList in the code below). This was something new for me. Previously I mistakenly thought "TThreadList" was a list of threads, whereas it's really a generic thread-safe list.

     

    The thread-safe pop and push procedures are as follows:

    function TForm1.PopFoo: TFoo;
    var
      xList: TList<TFoo>;
    begin
      xList := FooList.LockList;
      try
        if xList.Count > 0 then
        begin
          result := xList.Last;
          xList.Delete(xList.Count - 1);
        end
        else
          result := TFoo.Create;
      finally
        FooList.UnlockList;
      end;
    end;
    
    procedure TForm1.PushFoo(xFoo: TFoo);
    begin
      FooList.Add(xFoo);
    end;

    In case anyone is interested I've attached the full source of the example project.

     

    Thanks for the help,

     

    Steve

    Synchronize2.zip


  5. 2 minutes ago, David Heffernan said:

    It could still be related to the code that you have, which we don't have. 

     

    Anyway, it's a bad idea to force the code onto the main thread just to serialise it. Use a lock instead. 

    Hi David,

     

    Thanks for the input but I've just provided a complete example. See attached above. You have all the code.

     

    Based on your comment are you suggesting I mark the push and pop as Critical Sections? I haven't locked code before so please excuse my ignorance.

     

    Thank again,

     

    Steve

     


  6. See attached for a simplified example . The procedure "ProcessSingleThreaded" works as expected, but the procedure "ProcessMultiThreaded" freezes the system:

    procedure TForm1.ProcessMultiThreaded;
    var
      xBest: integer;
      i: integer;
    begin
    
      Screen.Cursor := crHourGlass;
    
      TParallel.&For(0, LoopSize - 1,
        procedure(j: integer)
        var
          xFoo: TFoo;
        begin
    
          //-- Get the Foo Object
          TThread.Synchronize(nil,
          procedure()
          begin
            xFoo := PopFoo;
          end);
    
          //-- Evaluate
          xFoo.Evaluate;
    
          //-- Push Back to the Stack
          TThread.Synchronize(nil,
          procedure()
          begin
            PushFoo(xFoo);
          end);
        end);
    
      xBest := 0;
      for i := 0 to FooList.Count - 1 do
        xBest := Max(xBest, FooList[i].BestValue);
    
      Form1.Caption := IntToStr(xBest);
    
      Screen.Cursor := crDefault;
    end;

    Why is the TThread.Synchronize freezing the application?

     

    All help appreciated,

     

    Thanks,

     

    Steve

    Synchronize.zip


  7. Hi David,

     

    PopNode and PushNode don't do anything special. I've listed the code below:

    function TOptimizer.PopNode: TOptNode;
    begin
      if fNodeStack.Count > 0 then
        result := fNodeStack.Pop
      else
      begin
        result := TOptNode.Clone(fMasterNode);
        fNodeList.Add(result);
      end;
    end;
    
    procedure TOptimizer.PushNode(xNode: TOptNode);
    begin
      fNodeStack.Push(xNode);
    end;

    All they do is either pop the Node if one already exists on the stack, or create a new node if the stack is empty. Clearly I don't want multiple threads popping and pushing at the same time. That's why the main thread should do all of the popping and pushing. 

     

    Thanks,

     

    Steve

     


  8. Hi Everyone,

     

    This could well be a complete "noob" question as I'm not that experienced with the parallel library.

     

    My objective is to utilize a parallel "for loop" in my optimization algorithm. Here's the code:

        TParallel.&For(0, fCriteria.Population - 1, procedure(i: integer)
          var
            xNode: TOptNode;
          begin
    
            //-- Get the latest node
            TThread.Synchronize(nil,
              procedure
              begin
                xNode := PopNode;
              end);
    
            //-- Get the new centers
            xNode.GenerateNewCenters;
    
            //-- Evaluate new centers
            xNode.Evaluate;
    
            //-- Push the node back onto the stack
            TThread.Synchronize(nil,
              procedure
              begin
                PushNode(xNode);
              end);
          end);

    Each iteration of the loop tests a new scenario (xNode.GenerateNewCenters) and stores the best one found (xNode.Evaluate). The TOptNode holds all the data that needs to be optimized. It's a large object and takes significant time to be created.  So I've created a TStack of TOptNode object, and only create them when needed. I need to be able to "pop" the xNode objects off the stack and "push" them back on in a thread safe way. I would have thought the code above would work, instead it just freezes when it comes to the "for" loop.

     

    What's the best way to "push" and "pop" in a thread safe manner inside of a parallel "for loop"?

     

    Thanks,

     

    Steve


  9. 1 hour ago, Sherlock said:

    OMG, that website is a total turnoff.

    Sorry 4 the OT.

     

     

    It's one of Joe Hecht's sites. He has a few and they all look the same. I gave him some similar honest feedback over on Google+ a few years' ago. He agreed, but nothing seems to have changed. It's a pity since I'm sure the components are decent. It would take no more than two days to replace these sites with a good WordPress theme.

    • Like 1

  10. 1 hour ago, Arnaud Bouchez said:

    Look into our OpenSource https://github.com/synopse/SynPDF project.

    It is free, fast, creates small PDF, and you can draw your content using a regular VCL TCanvas: the same code could be used on screen and for the PDF.

     

    Also note that there is no "resolution" in PDF, which is uses floating-point coordinates for its vectorial drawings.
    If you generate from a TCanvas, your code will use integers, so here you may need to tune the resolution - just like with any VCL code.

    Interesting!! I'll take a closer look.

     

    Thanks,

     

    Steve


  11. I'm looking to implement high-definition printing and exporting for our mapping application. I'm planning to do this by creating a PDF. The solution will need to be able to create PDFs with custom polygons at a desired resolution.

     

    I've done a brief search and Gnostice's eDocEngine seems to fit the bill. Before I dive in I thought I'd ask if anyone had any other suggestions or any feedback about Gnostice's solution,

     

    Thanks,

     

    Steve

×