Jump to content

Jud

Members
  • Content Count

    118
  • Joined

  • Last visited

Posts posted by Jud


  1. 1 hour ago, Ian Branch said:

    GExperts works fine in D12...

    I was going to the old website and I didn't notice that it is now done by someone else with a different website.  I just downloaded it - thanks for telling me that.

     

    * I have it installed, but I can't find an option to prevent a second instance of the IDE from starting.  Where is that option?


  2. 9 hours ago, dummzeuch said:

    I'm not aware of such a warning in Delphi, but GExperts shows one. It's enabled by default and can be disabled in the dialog itself. To enable it again later, go to the messages tab in the GExperts configuration dialog.

    I used GExperts for years, but it doesn't work with Delphi 12,   That was probably what I was using.


  3. It used to be that if I started a second instance of the Delphi IDE, it would warn me and ask if I wanted to start another instance.  Now it doesn't ask - I sometimes have 2, 3, or 4 instances running inadvertently, which I want to avoid.  I got a new computer with Windows 11 instead of 10, and I've upgraded Delphi. 

     

    Is there a setting in Delphi that warns you about starting a second instance?  Is it a Windows setting? (I know how to keep a second instance of my program from running.)


  4. I'm having a strange problem in the Delphi 12 IDE on a Windows 11 desktop.  First I downloaded the trial version of Enterprise and entered my license number.  (My license is for the professional edition.) There were strange problems in the IDE.  When searching, if I searched for "xyz[" or "xyz(", it would give an error message about mismatched [ or (, and not search.  If I search for ".xyz", it ignores the period.  There are other things, like much of refactor is disabled.  Sometimes "find declaration" doesn't work.

     

    I uninstalled Delphi 12 and reinstalled it from the iso file.  I had the same problems.

     

    Then about 3 weeks ago I installed it on my Windows 11 laptop to take on a trip.  It DOES NOT have the problems!

     

    What could cause this and how can it be fixed?

     

     


  5. 10 hours ago, DelphiUdIT said:

    I think that with regular account (subscription active) you cannot use CE.

     

     

    That seems to be the case, based on my experience.  I don't want to go through the hassle of activating it on my laptop, so I'm planning to use my wife's email to get the CE on my laptop. 


  6. I'm a long-time registered user of Delphi.  I want to download Delphi Community Edition to my laptop to take on a trip.  When I download the community edition, it gives me three options: sign up for trial version, enter a registration key, or upload a registration file. I just want to use the free community edition, but that isn't an option.  When I enter my registration code for 11.3, it says that it is registered to a different user, so I can't register it.

     

    Is there a way for me to just get the community edition for my laptop?


  7. 15 hours ago, Jud said:

    I've had a perplexing problem for about 2 days. Basically if a tTask is inside a loop, the loop isn't executed. I extracted a section of code from my program, and the short sample code below has the problem.  After the SetLength line is executed, it goes to the END of the procedure.  

     

    ==================

    More information:

     

    1. Sometimes the demo works. 

     

    2. But when that isn't working, the program skips the loop (doesn't even go to the FOR statement) and goes to the END of the procedure.  Then it locks up big time.  After a few seconds, it gives a stack overflow message, and it points to various places in System units (there doesn't seem to be a pattern).  It locks up so bad that I can't Close Window or end it with the task manager.  I have to restart the computer.

     

    3. I remembered that you can't call a procedure that depends on the value of the loop counter that way.  The only way I know to do it is to call a procedure from within the loop and that procedure sets up task and runs it.  So I'm going to make that change and I expect it will fix the problem.

     


  8. I've had a perplexing problem for about 2 days. Basically if a tTask is inside a loop, the loop isn't executed. I extracted a section of code from my program, and the short sample code below has the problem.  After the SetLength line is executed, it goes to the END of the procedure.  

    This used to work.  If I take the line TaskArray[ counter] := - the loop is executed. If I take out the loop and replace it by counter := 0, it works.

    Am I missing something?  What is going wrong?


    procedure TForm2.RunButtonClick(Sender: TObject);

    const NumberOfParts = 1;

    var counter : integer;
        TaskArray : array of iTask;

    begin { --- run button --- }
    SetLength( TaskArray, NumberOfParts);

    for counter := 0 to NumberOfParts - 1 do
    begin
      try
        TaskArray[ counter] := tTask.run( procedure
          begin
            RunWork( counter);
          end);
      except on E:EAggregateException do ShowMessage( E.ToString);
      end; // try
    end; // for counter
    end; { --- run button --- }

     


  9. 6 hours ago, programmerdelphi2k said:

    I think that "ProcessMessages" it's not necessary.

    you can use "Synchronize" (wait me ...)  or "Queue" (dont wait me ...)

    5 hours ago, Dalija Prasnikar said:

     

    You should remove Application.ProcessMessages from that code as it serves no purpose. 

     

    I took that out. 

    Also, I just realized that I made a mistake.  I was using tThread.synchronize in one place and tThread.queue in another place, writing to the same memo, and the data was not matching.  It seems that thread.queue is NOT thread-safe for doing this.

     

    It is working now, thanks everyone!

     


  10. I need to write to a memo on the main form from within a thread.  In an old program using tasks I was doing this:

     

    tThread.synchronize( tThread.current, procedure
    begin
      form1.TestMemo.lines.add( 'Testing ');
      application.ProcessMessages;
    end);

     

    and it was working.  I put the same type of thing in a tread called by the parallel for, but it isn't writing to the memo. 

     

    Is there a different way to do it from a thread called from a parallel for? 


  11. 1 hour ago, David Heffernan said:

    Depending on what you do when you query these bits you may find that the memory is the bottleneck and threading won't help. Did you do any benchmarking yet? 

     

    Also if performance matters then delphi is invariably not the answer. 

     

    Actually I did benchmarking.  The first version of this program read a 30GB boolean array from a drive and used that.  Naturally I did a single-thread before multithreading.  I forgot the ratio, but 20 threads on a 12th generation i7 was something like 8-9x faster than the single-thread version.  Now I'm working on replacing the 30GB boolean array with a much larger bit vector.

     


  12. 49 minutes ago, David Heffernan said:

    Depending on what you do when you query these bits you may find that the memory is the bottleneck and threading won't help. Did you do any benchmarking yet? 

     

    Also if performance matters then delphi is invariably not the answer. 

    No benchmarking with the bit vector yet, but I've definitely encountered the memory bottleneck.  In old tests with 8 threads (hyperthreaded 4-core i7), I would get about 5.5x over a single thread on CPU-intensive tasks.  But on tests that were memory-intensive, I would get around 3x on 16 threads.


  13. 9 hours ago, David Heffernan said:
    
    unit Bitset;
    
    interface
    
    uses
      SysUtils, Math;
    
    type
      TBitSet = record
      private
        FBitCount: Int64;
        FSets: array of set of 0..255;
        class function SetCount(BitCount: Int64): Int64; static;
        procedure MakeUnique;
        procedure GetSetIndexAndBitIndex(Bit: Int64; out SetIndex: Int64; out BitIndex: Integer);
        function GetIsEmpty: Boolean;
        procedure SetBitCount(Value: Int64);
        function GetSize: Int64;
      public
        class operator In(const Bit: Int64; const BitSet: TBitSet): Boolean;
        class operator Equal(const bs1, bs2: TBitSet): Boolean;
        class operator NotEqual(const bs1, bs2: TBitSet): Boolean;
        property BitCount: Int64 read FBitCount write SetBitCount;
        property Size: Int64 read GetSize;
        property IsEmpty: Boolean read GetIsEmpty;
        procedure Clear;
        procedure IncludeAll;
        procedure Include(const Bit: Int64);
        procedure Exclude(const Bit: Int64);
      end;
    
    
    implementation
    
    { TBitSet }
    
    procedure TBitSet.MakeUnique;
    begin
      // this is used to implement copy-on-write so that the type behaves like a value
      SetLength(FSets, Length(FSets));
    end;
    
    procedure TBitSet.GetSetIndexAndBitIndex(Bit: Int64; out SetIndex: Int64; out BitIndex: Integer);
    begin
      Assert(InRange(Bit, 0, FBitCount-1));
      SetIndex := Bit shr 8;   // shr 8   = div 256
      BitIndex := Bit and 255; // and 255 = mod 256
    end;
    
    function TBitSet.GetIsEmpty: Boolean;
    var
      i: Int64;
    begin
      for i := 0 to High(FSets) do begin
        if FSets[i]<>[] then begin
          Result := False;
          Exit;
        end;
      end;
    
      Result := True;
    end;
    
    procedure TBitSet.SetBitCount(Value: Int64);
    var
      Bit, BitIndex: Integer;
      SetIndex: Int64;
    begin
      if (Value<>FBitCount) or not Assigned(FSets) then begin
        Assert(Value>=0);
        FBitCount := Value;
        SetLength(FSets, SetCount(Value));
        if Value>0 then begin
          (* Ensure that unused bits are cleared, necessary give the CompareMem call in Equal. This also
             means that state does not persist when we decrease and then increase BitCount. For instance,
             consider this code:
               var
                 bs: TBitSet;
               ...
               bs.BitCount := 2;
               bs.Include(1);
               bs.BitCount := 1;
               bs.BitCount := 2;
               Assert(not (1 in bs)); *)
          GetSetIndexAndBitIndex(Value - 1, SetIndex, BitIndex);
          for Bit := BitIndex + 1 to 255 do begin
            System.Exclude(FSets[SetIndex], Bit);
          end;
        end;
      end;
    end;
    
    function TBitSet.GetSize: Int64;
    begin
      Result := Length(FSets)*SizeOf(FSets[0]);
    end;
    
    class function TBitSet.SetCount(BitCount: Int64): Int64;
    begin
      Result := (BitCount + 255) shr 8; // shr 8 = div 256
    end;
    
    class operator TBitSet.In(const Bit: Int64; const BitSet: TBitSet): Boolean;
    var
      SetIndex: Int64;
      BitIndex: Integer;
    begin
      BitSet.GetSetIndexAndBitIndex(Bit, SetIndex, BitIndex);
      Result := BitIndex in BitSet.FSets[SetIndex];
    end;
    
    class operator TBitSet.Equal(const bs1, bs2: TBitSet): Boolean;
    begin
      Result := (bs1.FBitCount=bs2.FBitCount)
        and CompareMem(Pointer(bs1.FSets), Pointer(bs2.FSets), bs1.Size);
    end;
    
    class operator TBitSet.NotEqual(const bs1, bs2: TBitSet): Boolean;
    begin
      Result := not (bs1=bs2);
    end;
    
    procedure TBitSet.Clear;
    var
      i: Int64;
    begin
      MakeUnique;
      for i := 0 to High(FSets) do begin
        FSets[i] := [];
      end;
    end;
    
    procedure TBitSet.IncludeAll;
    var
      i: Int64;
    begin
      for i := 0 to BitCount-1 do begin
        Include(i);
      end;
    end;
    
    procedure TBitSet.Include(const Bit: Int64);
    var
      SetIndex: Int64;
      BitIndex: Integer;
    begin
      MakeUnique;
      GetSetIndexAndBitIndex(Bit, SetIndex, BitIndex);
      System.Include(FSets[SetIndex], BitIndex);
    end;
    
    procedure TBitSet.Exclude(const Bit: Int64);
    var
      SetIndex: Int64;
      BitIndex: Integer;
    begin
      MakeUnique;
      GetSetIndexAndBitIndex(Bit, SetIndex, BitIndex);
      System.Exclude(FSets[SetIndex], BitIndex);
    end;
    
    end.

    This is based on code of mine that has is limited to integer bit count. I've not tested it extended to Int64, but I'm sure anyone that wanted to use random code like this would test.

    That looks like what I'm looking for!!! I'm going to try it shortly.  Thanks!


  14. 9 hours ago, David Heffernan said:
    
    unit Bitset;
    
    interface
    
    uses
      SysUtils, Math;
    
    type
      TBitSet = record
      private
        FBitCount: Int64;
        FSets: array of set of 0..255;
        class function SetCount(BitCount: Int64): Int64; static;
        procedure MakeUnique;
        procedure GetSetIndexAndBitIndex(Bit: Int64; out SetIndex: Int64; out BitIndex: Integer);
        function GetIsEmpty: Boolean;
        procedure SetBitCount(Value: Int64);
        function GetSize: Int64;
      public
        class operator In(const Bit: Int64; const BitSet: TBitSet): Boolean;
        class operator Equal(const bs1, bs2: TBitSet): Boolean;
        class operator NotEqual(const bs1, bs2: TBitSet): Boolean;
        property BitCount: Int64 read FBitCount write SetBitCount;
        property Size: Int64 read GetSize;
        property IsEmpty: Boolean read GetIsEmpty;
        procedure Clear;
        procedure IncludeAll;
        procedure Include(const Bit: Int64);
        procedure Exclude(const Bit: Int64);
      end;
    
    
    implementation
    
    { TBitSet }
    
    procedure TBitSet.MakeUnique;
    begin
      // this is used to implement copy-on-write so that the type behaves like a value
      SetLength(FSets, Length(FSets));
    end;
    
    procedure TBitSet.GetSetIndexAndBitIndex(Bit: Int64; out SetIndex: Int64; out BitIndex: Integer);
    begin
      Assert(InRange(Bit, 0, FBitCount-1));
      SetIndex := Bit shr 8;   // shr 8   = div 256
      BitIndex := Bit and 255; // and 255 = mod 256
    end;
    
    function TBitSet.GetIsEmpty: Boolean;
    var
      i: Int64;
    begin
      for i := 0 to High(FSets) do begin
        if FSets[i]<>[] then begin
          Result := False;
          Exit;
        end;
      end;
    
      Result := True;
    end;
    
    procedure TBitSet.SetBitCount(Value: Int64);
    var
      Bit, BitIndex: Integer;
      SetIndex: Int64;
    begin
      if (Value<>FBitCount) or not Assigned(FSets) then begin
        Assert(Value>=0);
        FBitCount := Value;
        SetLength(FSets, SetCount(Value));
        if Value>0 then begin
          (* Ensure that unused bits are cleared, necessary give the CompareMem call in Equal. This also
             means that state does not persist when we decrease and then increase BitCount. For instance,
             consider this code:
               var
                 bs: TBitSet;
               ...
               bs.BitCount := 2;
               bs.Include(1);
               bs.BitCount := 1;
               bs.BitCount := 2;
               Assert(not (1 in bs)); *)
          GetSetIndexAndBitIndex(Value - 1, SetIndex, BitIndex);
          for Bit := BitIndex + 1 to 255 do begin
            System.Exclude(FSets[SetIndex], Bit);
          end;
        end;
      end;
    end;
    
    function TBitSet.GetSize: Int64;
    begin
      Result := Length(FSets)*SizeOf(FSets[0]);
    end;
    
    class function TBitSet.SetCount(BitCount: Int64): Int64;
    begin
      Result := (BitCount + 255) shr 8; // shr 8 = div 256
    end;
    
    class operator TBitSet.In(const Bit: Int64; const BitSet: TBitSet): Boolean;
    var
      SetIndex: Int64;
      BitIndex: Integer;
    begin
      BitSet.GetSetIndexAndBitIndex(Bit, SetIndex, BitIndex);
      Result := BitIndex in BitSet.FSets[SetIndex];
    end;
    
    class operator TBitSet.Equal(const bs1, bs2: TBitSet): Boolean;
    begin
      Result := (bs1.FBitCount=bs2.FBitCount)
        and CompareMem(Pointer(bs1.FSets), Pointer(bs2.FSets), bs1.Size);
    end;
    
    class operator TBitSet.NotEqual(const bs1, bs2: TBitSet): Boolean;
    begin
      Result := not (bs1=bs2);
    end;
    
    procedure TBitSet.Clear;
    var
      i: Int64;
    begin
      MakeUnique;
      for i := 0 to High(FSets) do begin
        FSets[i] := [];
      end;
    end;
    
    procedure TBitSet.IncludeAll;
    var
      i: Int64;
    begin
      for i := 0 to BitCount-1 do begin
        Include(i);
      end;
    end;
    
    procedure TBitSet.Include(const Bit: Int64);
    var
      SetIndex: Int64;
      BitIndex: Integer;
    begin
      MakeUnique;
      GetSetIndexAndBitIndex(Bit, SetIndex, BitIndex);
      System.Include(FSets[SetIndex], BitIndex);
    end;
    
    procedure TBitSet.Exclude(const Bit: Int64);
    var
      SetIndex: Int64;
      BitIndex: Integer;
    begin
      MakeUnique;
      GetSetIndexAndBitIndex(Bit, SetIndex, BitIndex);
      System.Exclude(FSets[SetIndex], BitIndex);
    end;
    
    end.

    This is based on code of mine that has is limited to integer bit count. I've not tested it extended to Int64, but I'm sure anyone that wanted to use random code like this would test.

     


  15. 11 hours ago, Rollo62 said:

    Like said, just an alternative idea, with pros and cons.

    Only @Jud may know if this is workable for him somehow, or not.

     

     

    I doubt that it would be workable, since they are natually one dimentional, and the program just needs to see if a bit is 1 or 0, and it needs to do a large number of them.


  16. 12 hours ago, David Heffernan said:

    What about the cost of moving data between gpu and main memory? Benefits of gpu are in highly parallel computation. Where is that in this scenario. Just saying GPU doesn't make something fast or efficient. 

    Interesting idea, but I don't know how to deal with the GPU.  This will be running 20 instances in parallel, but the accesses will be pretty much random.  The target calls for doing at least 10 trillion accesses.


  17. 17 hours ago, David Heffernan said:

    No. You use a hashed collection. Like a dictionary, but one without a value, which is known as a set. 

     

    But at 5% full then I don't think it will get you any benefit, because of the overhead of the hashed collection. 

     

    Performance is an issue.  The plan is to do at least 10 trillion accesses to the bit vector - more if I can manage it.

     

×