Recent

Author Topic: Why isn't Lazarus / Free Pascal more popular?  (Read 18227 times)

PascalDragon

  • Hero Member
  • *****
  • Posts: 5968
  • Compiler Developer
Re: Why isn't Lazarus / Free Pascal more popular?
« Reply #60 on: April 29, 2025, 10:06:33 pm »
I was curious to why it so and was not too lazy to look at the assembly code for MonteCarlo benchmark.
In short VC++ has made most procedures as inline even though it was not asked to do so.
Whereas Lazarus left half of the procedures marked as inline as callable procedures (obviously oriented on their size).
In addition VC++ rethought the sequence of actions in some procedures (for example, in the Random_nextDouble procedure), while Lazarus clearly did everything as it was told in the source.
As a result, we got a code that works in this particular algorithm 4.5 times faster actually from the same sources.

What you seem to forget is compilers like GCC, VC++, clang & LLVM , Java etc. have many contributors and commercial backing of big companies that can afford to sink tons of time and money into improvements. FPC on the other hand is developed by around two handful of developers in their free time of which not all have much or any experience at all with implementing and/or improving optimizations.

Also the LLVM backend won't be the be-all-end-all solution. Not to mention that LLVM does not even support floating point exceptions which is something that Object Pascal does support and thus the LLVM backend will lead to degradation in functionality. The LLVM backend will only ever be an option, but never a full replacement.

Lenny33

  • New Member
  • *
  • Posts: 37
Re: Why isn't Lazarus / Free Pascal more popular?
« Reply #61 on: April 30, 2025, 01:54:38 am »
FPC on the other hand is developed by around two handful of developers in their free time of which not all have much or any experience at all with implementing and/or improving optimizations.
I'm well aware of that. And it is OK for open source project.
But that's just why I argue that using FPC for heavy computations is at least not reasonable. And that's why we moved all data calculations in our application to C++ libraries.

It is bad that commercial and not cheap at all Delphi also generate the same bad optimized code. They are spending money on something else  :(
« Last Edit: April 30, 2025, 10:24:20 am by Lenny33 »

VisualLab

  • Hero Member
  • *****
  • Posts: 678
Re: Why isn't Lazarus / Free Pascal more popular?
« Reply #62 on: April 30, 2025, 12:19:27 pm »
Apparently it seems young farts are more susceptible to pointless popularity contests.
It's simple. Young farts look where there's more potential and money-making opportunities ;)

Agreed about making money.

But what do you mean by "more potential"? From what I have noticed, young potential programmers want programming to be convenient, easy, and that programs (solutions to problems) can be written (created) as quickly as possible. And that is of course OK. But the question arises: "how to achieve this"? And here's the crux of the matter. If that is achieved by improving and extending tools like compilers, debuggers, libraries and IDEs, then OK. But mastering all that, gaining experience in using it, takes time (a lot of it, really). And young people are mostly impatient and lazy (not all, but most are). The young (generally) want:
  • ready libraries for everything, i.e. for every problem to be already solved and they can just put it all together from ready-made "frameworks",
  • easy programming language (simple syntax, without fancy mechanisms, especially allocating and freeing memory areas),
  • it would be best if the programs "almost" wrote themselves (hence the huge popularity of AI).
That's what everyone would like. Their answer (usually) is: Python or JavaScript (Electron) - for everything. Even for programming microcontrollers. Because it's easy. And that's true (to some extent). But the cost is quality (really low), execution time, resistance to errors, etc. Only the young don't care, because it's a cost that the user bears, after all it's them who struggle with such a "ball of mud".

Compared to "popular" technologies, C++ is solid (but not without flaws). In principle, choosing C++ has one big advantage: the code generated by compilers is well optimized. And it's also true that C++ is more often used by the young than Object Pascal, probably mainly for the above reason. So the enthusiasm of young programmers towards C++ is very moderate. A significant percentage of young people learn C++, but it is learning with gritted teeth.

The rest of the young people (who avoid C++) do not realize that some of their requirements are met by ObjectPascal. But they prefer "colorful" propaganda.

It is bad that commercial and not cheap at all Delphi also generate the same bad optimized code. They are spending money on something else  :(

This is a problem that has been going on for many years and started when Borland was still alive. People in the management of this company (Idera) simply have no concept of developing a compiler and IDE (and probably their company as well). They spend the money they earn on nonsense. This company survives but does not develop.
« Last Edit: April 30, 2025, 12:38:34 pm by VisualLab »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12206
  • FPC developer.
Re: Why isn't Lazarus / Free Pascal more popular?
« Reply #63 on: April 30, 2025, 12:31:05 pm »
Delphi was meant as a 4GL database tool, not a number cruncher. Hence the optimisation that goes to a decent level, but not further. Same with missing intrinsics and other HPC features.

Khrys

  • Full Member
  • ***
  • Posts: 229
Re: Why isn't Lazarus / Free Pascal more popular?
« Reply #64 on: April 30, 2025, 01:10:28 pm »
And young people are mostly impatient and lazy (not all, but most are).

And old people have been calling the younger generations impatient and lazy for thousands of years, yet humanity is still around   ;)

silvercoder70

  • Full Member
  • ***
  • Posts: 186
    • Tim Coates
Re: Why isn't Lazarus / Free Pascal more popular?
« Reply #65 on: April 30, 2025, 02:46:40 pm »
The rest of the young people (who avoid C++) do not realize that some of their requirements are met by ObjectPascal. But they prefer "colorful" propaganda.

And they probably don't realise this because once they hear the name Pascal.... Will think of the old Turbo Pascal they might save seem or used in school—procedural, DOS-based, and outdated. And when you combine that with a lack of visibility...  Object Pascal doesn’t get much visibility in mainstream programming media compared to languages like Python or JavaScript.

Now... because I genuinely like the language, (as most of you know?) I started a YouTube channel to (in my own small way) help change that. I'm trying to show that Pascal is very much alive and capable today. Honestly, I also got tired of hearing that it's a dead language—there's real value in it, and if I can help shift a few perceptions, that’s a win. Isn't it?

We each have our own (little) role to play in that regard.
« Last Edit: April 30, 2025, 11:23:26 pm by silvercoder70 »
🔥 Pascal Isn’t Dead -> See What It Can Do: @silvercoder70 on YouTube

LV

  • Sr. Member
  • ****
  • Posts: 272
Re: Why isn't Lazarus / Free Pascal more popular?
« Reply #66 on: May 01, 2025, 07:59:19 am »
But that's just why I argue that using FPC for heavy computations is at least not reasonable.

When it comes to real projects, choosing FPC proves to be a reasonable and effective choice.
https://doi.org/10.14201/adcaij.31762
Also, thanks to @jwdietrich for the source codes.
https://doi.org/10.5281/zenodo.8317319

On the other hand, the performance of heavy computations, such as matrix operations, is comparable:  ;)
FPC & OpenBlas;
C++ & MKL;
Python & NumPy

michaelthuma

  • Jr. Member
  • **
  • Posts: 51
Re: Why isn't Lazarus / Free Pascal more popular?
« Reply #67 on: May 01, 2025, 12:45:52 pm »
Hi,
Maybe I'm not the first one who is wondering about why Lazarus isn't more popular amongst developers?

...

Despite all of those facts Free Pascal seems to be a dying language. Most of the devs seem to use it for many years, working on legacy software, which makes me think that the majority of devs is a bit older.

The popularity of  a programming language doesn't say a lot in a sense of an objective measure. You never know what really drives the hype.

In the big picture object orientation reflects the progressive roots of programming languages tied to this paradigm and foundations of marketing over the last decades. On thing that went out of scope over the 1990s was the dependency on geostrategic issues concerning hardware and especially processor architecture.

The real reason for the boom in the 1990s, let's say the biggest enabler ever, was the fall of 'The Iron Curtain'. That changed a lot and allowed to focus progress. With the progressive perspective the system/overall perspective again started to dominate.

The latter was the real enabler for the PC and the Wintel dominance the stabilizing factor, which gave the more centralistic computer architectures time to reinvent themselves and/or the vendors.

The very late 1980s, the 1990s and mid of the first decade after the shift into this century was dominated by step by step reintroducing concepts (e.g. JIT, pretty old ideas) concerning platform agnostic considerations and solutions addressing such issues. The 1990s in the end were about Software for Desktops, Internet in the beginning and taking the opportunity to get rid of the big more or less monolithic hardware and software systems and together with those the old problems that came with COBOL, IBM Assembler, lots of other technical legacy from the the decades before and pushing the finance industry into a much much higher level aka. 'Y2K'.

The counterforce has always been, that never really changed, that source code is the most 'conservative' beast once introduced or put live.

I have no doubt that FPC/Lazarus especially will stay and will be used. Apart from the fact, that the only customer or user of which I have to take care is myself, most of my boxes rely on instant-fpc as the preferred way of scripting for example. There is nothing wrong with anything else and more of the same is accepted nowadays, pretty similar to the end of the 1980s and the time before.

When I attended university, University of Linz/Austria was on Modula and Oberon these days too, because of the Swiss as a neighbor country and the ETH Zurich as certain kind of ideas giving ideal and I used Quick Pascal for the very first lessons in Algorithms I/II. These days the mainstream was the opposite of today. The symbols used in a rebel stand vary. Kidding. The only option for Modula II compilers on a PC was the Topspeed IDE, with different languages on the frontend compiling to one backend. That company went broke, so there was a certain struggle between the dominant Turbo/Borland Pascal compilers, the Modula II compiler and me the one who used Quick Pascal 1.0.

AmatCoder

  • Jr. Member
  • **
  • Posts: 67
    • My site
Re: Why isn't Lazarus / Free Pascal more popular?
« Reply #68 on: May 01, 2025, 02:30:55 pm »
In summary:
Quote from: CM630
Delphi was really popular before .Net.
Then MS hired Hejsberg, Sun kept on developing Java.
Delphi became expensive, Lazarus did not grow up in a day and [it] was [too] late.
This.

Quote from: 440bx
When it comes to UI components, I remember when I was looking at C#, just about anything I could dream of as far as interface widget was available or easily obtainable by making small modifications to an existing widget.
That's what Lazarus is competing with, the .net framework and all the gizmos it provides [to] the programmer.
This.

Quote from: Khrys
Pascal itself is perceived as old & outdated. And with the abundance of alternatives nowadays, only few give it the benefit of the doubt.
Modern Pascal may support classes, generics, operator overloading, automatic reference counting and the like, but it seems that nothing can overcome historical inertia (C, C++) and backing by massive corporations (C#, Go).
And this.

BeniBela

  • Hero Member
  • *****
  • Posts: 927
    • homepage
Re: Why isn't Lazarus / Free Pascal more popular?
« Reply #69 on: May 01, 2025, 11:06:11 pm »
I might have missed/forgotten a few of the "Request & promise" features that have been brought forward during the years.  Maybe "inline var declarations", and "anonymous functions" ... (the latter is in FPC 3.3.1)

you already need that for Delphi compatibility.

People used to switch from Delphi to FreePascal when Delphi becomes too expensive, and without Delphi compatibility they cannot do that anymore

Borland should have made Delphi open source. Maybe it would be more popular if the user base ẃas not split between  Delphi and FreePascal



Speed, strangely has IIRC only been on the "absent complaints" list, but hasn't come with that promise. Which IHMO at least is a plus point towards the honesty of those complaining about it.

The speed was already good

I use Pascal precisely because I was told that it was faster than Java


Perhaps people were lying to me. Or it has gotten worse over the years.

but in some cases it is still faster than C++: https://forum.lazarus.freepascal.org/index.php/topic,69777.0.html


AmatCoder

  • Jr. Member
  • **
  • Posts: 67
    • My site
Re: Why isn't Lazarus / Free Pascal more popular?
« Reply #70 on: May 02, 2025, 11:09:26 am »
Quote from: BeniBela
but in some cases it is still faster than C++: https://forum.lazarus.freepascal.org/index.php/topic,69777.0.html

I don't mean to be offensive...but I must to say it: That benchmark is just ridiculous.  :o

PascalDragon

  • Hero Member
  • *****
  • Posts: 5968
  • Compiler Developer
Re: Why isn't Lazarus / Free Pascal more popular?
« Reply #71 on: May 02, 2025, 09:37:04 pm »
People used to switch from Delphi to FreePascal when Delphi becomes too expensive, and without Delphi compatibility they cannot do that anymore

If users really require inline variables to live then they should ask themselves whether a Pascal language is really the right choice for them. Inline variables have no place here.

LV

  • Sr. Member
  • ****
  • Posts: 272
Re: Why isn't Lazarus / Free Pascal more popular?
« Reply #72 on: May 02, 2025, 10:15:20 pm »
As everyone can see VC++ created code that executes almost twice as fast as the code created by Lazarus.

Okay, let's multiply two 1000x1000 matrices.

GFortran (GCC out of the box codeblocks-25.03), Optimize fully (for speed) [-O3]:

Code: Fortran  [Select][+][-]
  1. program matrix_multiplication
  2.     implicit none
  3.     integer, parameter :: n = 1000
  4.     real(8), dimension(n,n) :: A, B, C
  5.     real(8) :: t_start, t_end
  6.     integer :: i, j, k
  7.  
  8.     call random_seed()
  9.  
  10.  
  11.     call fill_random(A)
  12.     call fill_random(B)
  13.  
  14.     C = 0.0d0
  15.  
  16.     call CPU_TIME(t_start)
  17.  
  18.     do i = 1, n
  19.         do j = 1, n
  20.             do k = 1, n
  21.                 C(i,j) = C(i,j) + A(i,k) * B(k,j)
  22.             end do
  23.         end do
  24.     end do
  25.  
  26.     call CPU_TIME(t_end)
  27.  
  28.     print *, 'Fortran Execution Time, ms: ', int((t_end - t_start) * 1000)
  29.  
  30. contains
  31.  
  32.     subroutine fill_random(matrix)
  33.         real(8), dimension(n,n), intent(out) :: matrix
  34.         real(8), dimension(n,n) :: r
  35.         call random_number(r)
  36.         matrix = r * 100.0d0
  37.     end subroutine fill_random
  38.  
  39. end program matrix_multiplication
  40.  

Output:

Fortran Execution Time, ms:         1140


C++ (GCC out of the box codeblocks-25.03), Optimize fully (for speed) [-O3]:

Code: C++  [Select][+][-]
  1. #include <iostream>
  2. #include <vector>
  3. #include <random>
  4. #include <chrono>
  5.  
  6. const int N = 1000;
  7.  
  8. int main() {
  9.  
  10.     std::vector<std::vector<double>> A(N, std::vector<double>(N));
  11.     std::vector<std::vector<double>> B(N, std::vector<double>(N));
  12.     std::vector<std::vector<double>> C(N, std::vector<double>(N, 0.0));
  13.  
  14.  
  15.     std::random_device rd;
  16.     std::mt19937 gen(rd());
  17.     std::uniform_real_distribution<> dist(0.0, 100.0);
  18.  
  19.  
  20.     for (int i = 0; i < N; ++i)
  21.         for (int j = 0; j < N; ++j) {
  22.             A[i][j] = dist(gen);
  23.             B[i][j] = dist(gen);
  24.         }
  25.  
  26.  
  27.     auto start = std::chrono::high_resolution_clock::now();
  28.  
  29.  
  30.     for (int i = 0; i < N; ++i)
  31.         for (int j = 0; j < N; ++j)
  32.             for (int k = 0; k < N; ++k)
  33.                 C[i][j] += A[i][k] * B[k][j];
  34.  
  35.  
  36.     auto end = std::chrono::high_resolution_clock::now();
  37.     std::chrono::duration<double> elapsed = end - start;
  38.  
  39.     std::cout << "Cpp Execution Time, ms:            " << int(elapsed.count() * 1000) << std::endl;
  40.     std::cin.get();
  41.  
  42.     return 0;
  43. }
  44.  

Output:

Cpp Execution Time, ms:            1433

FPC 3.2.2, Optimize [-O3]:

Code: Pascal  [Select][+][-]
  1. program MatrixMultiply;
  2.  
  3. uses
  4.   SysUtils, DateUtils;
  5.  
  6. const
  7.   N = 1000;
  8.  
  9. type
  10.   TMatrix = array[0..N-1, 0..N-1] of Double;
  11.  
  12. var
  13.   A, B, C: TMatrix;
  14.   i, j, k: Integer;
  15.   StartTime, EndTime: Int64;
  16.  
  17. procedure FillRandom(var M: TMatrix);
  18. var
  19.   i, j: Integer;
  20. begin
  21.   Randomize;
  22.   for i := 0 to N - 1 do
  23.     for j := 0 to N - 1 do
  24.       M[i, j] := Random * 100;
  25. end;
  26.  
  27. begin
  28.   FillRandom(A);
  29.   FillRandom(B);
  30.  
  31.   StartTime := GetTickCount64;
  32.  
  33.   for i := 0 to N - 1 do
  34.     for j := 0 to N - 1 do
  35.     begin
  36.       C[i, j] := 0;
  37.       for k := 0 to N - 1 do
  38.         C[i, j] := C[i, j] + A[i, k] * B[k, j];
  39.     end;
  40.  
  41.   EndTime := GetTickCount64;
  42.   Writeln('FPC Execution Time, ms:         ', (EndTime - StartTime));
  43.   Readln;
  44. end.
  45.  

Output:

FPC Execution Time, ms:         2437

FPC 3.2.2, Manual vector optimization:

Code: Pascal  [Select][+][-]
  1. program avxmatrixmult;
  2. {$mode objfpc}
  3. {$ASMMODE INTEL}
  4. {$OPTIMIZATION LEVEL3}
  5.  
  6. uses
  7.   SysUtils,
  8.   Math,
  9.   Windows,
  10.   Classes;
  11.  
  12. const
  13.   MATRIX_SIZE = 1000;
  14.   MATRIX_ELEMENTS = MATRIX_SIZE * MATRIX_SIZE;
  15.   ALIGN_SIZE = 32;
  16.   EPSILON = 1e-6;
  17.   THREAD_COUNT = 6;
  18.  
  19. type
  20.   TAlignDoubleArray = array[0..0] of Double;
  21.   PAlignDoubleArray = ^TAlignDoubleArray;
  22.  
  23.   TThreadData = record
  24.     a: PAlignDoubleArray;
  25.     b_transposed: PAlignDoubleArray;
  26.     c: PAlignDoubleArray;
  27.     start_row, end_row: Integer;
  28.   end;
  29.   PThreadData = ^TThreadData;
  30.  
  31. var
  32.   a, b, b_transposed, c_avx, c_naive: PAlignDoubleArray;
  33.  
  34. {------------------- Memory Management --------------------}
  35. function AlignedArrayAlloc(size: Integer): PAlignDoubleArray;
  36. var
  37.   originalPtr: Pointer;
  38.   alignedAddr: Pointer;
  39. begin
  40.   GetMem(originalPtr, size * SizeOf(Double) + ALIGN_SIZE - 1 + SizeOf(Pointer));
  41.   alignedAddr := originalPtr;
  42.   Inc(PByte(alignedAddr), SizeOf(Pointer));
  43.   alignedAddr := Pointer((PtrUInt(alignedAddr) + ALIGN_SIZE - 1) and not (ALIGN_SIZE - 1));
  44.   Result := PAlignDoubleArray(alignedAddr);
  45.   PPointer(PByte(Result) - SizeOf(Pointer))^ := originalPtr;
  46. end;
  47.  
  48. procedure AlignedArrayFree(arr: PAlignDoubleArray);
  49. begin
  50.   if Assigned(arr) then
  51.     FreeMem(PPointer(PByte(arr) - SizeOf(Pointer))^);
  52. end;
  53.  
  54. {------------------- AVX Support Check --------------------}
  55. function IsAVXSupported: Boolean;
  56. var
  57.   _ecx: LongInt;
  58. begin
  59.   asm
  60.     mov eax, $1
  61.     cpuid
  62.     mov _ecx, ecx
  63.   end;
  64.   Result := (_ecx and (1 shl 28)) <> 0;
  65. end;
  66.  
  67. {------------------- Matrix Transposition -----------------}
  68. procedure TransposeMatrix(const src, dst: PAlignDoubleArray);
  69. var
  70.   i, j: Integer;
  71. begin
  72.   for i := 0 to MATRIX_SIZE - 1 do
  73.     for j := 0 to MATRIX_SIZE - 1 do
  74.       dst^[j * MATRIX_SIZE + i] := src^[i * MATRIX_SIZE + j];
  75. end;
  76.  
  77. {------------------- Thread Worker ------------------------}
  78. function AVXThreadWorker(Data: Pointer): PtrInt;
  79. var
  80.   ThreadData: PThreadData;
  81. begin
  82. asm
  83.   push rbx
  84.   push r12
  85.   push r13
  86.   push r14
  87.   push r15
  88.   push rdi
  89.   push rsi
  90.  
  91.   mov r15, Data
  92.   mov r14, [r15 + TThreadData.a]
  93.   mov r13, [r15 + TThreadData.b_transposed]
  94.   mov r12, [r15 + TThreadData.c]
  95.   mov edi, [r15 + TThreadData.start_row]
  96.   mov esi, [r15 + TThreadData.end_row]
  97.  
  98. @outer_loop:
  99.   cmp edi, esi
  100.   jge @exit
  101.  
  102.   xor ebx, ebx
  103. @middle_loop:
  104.   // Calculate base addresses for A[i] and B_transposed[j]
  105.   mov eax, edi
  106.   imul eax, MATRIX_SIZE
  107.   shl eax, 3  // eax = i * MATRIX_SIZE * 8
  108.   mov r10, rax
  109.  
  110.   mov eax, ebx
  111.   imul eax, MATRIX_SIZE
  112.   shl eax, 3  // eax = j * MATRIX_SIZE * 8
  113.   mov r11, rax
  114.  
  115.   vxorpd ymm0, ymm0, ymm0
  116.   vxorpd ymm1, ymm1, ymm1
  117.   vxorpd ymm2, ymm2, ymm2
  118.   vxorpd ymm3, ymm3, ymm3
  119.  
  120.   xor ecx, ecx  // k = 0
  121. @inner_loop:
  122.   // Calculate offset for A[i][k] and B_transposed[j][k]
  123.   mov rax, rcx
  124.   shl rax, 3    // rax = k * 8
  125.   add rax, r10  // rax = i*MATRIX_SIZE*8 + k*8
  126.  
  127.   mov rdx, rcx
  128.   shl rdx, 3    // rdx = k * 8
  129.   add rdx, r11  // rdx = j*MATRIX_SIZE*8 + k*8
  130.  
  131.   vmovapd ymm4, [r14 + rax]      // Load A[i][k]
  132.   vmovapd ymm5, [r13 + rdx]      // Load B_transposed[j][k]
  133.   vfmadd231pd ymm0, ymm4, ymm5   // Accumulate
  134.  
  135.   vmovapd ymm6, [r14 + rax + 32] // Load A[i][k+4]
  136.   vmovapd ymm7, [r13 + rdx + 32] // Load B_transposed[j][k+4]
  137.   vfmadd231pd ymm1, ymm6, ymm7
  138.  
  139.   add ecx, 8                     // Process 8 elements per iteration
  140.   cmp ecx, MATRIX_SIZE
  141.   jl @inner_loop
  142.  
  143.   // Horizontal sum
  144.   vaddpd ymm0, ymm0, ymm1
  145.   vaddpd ymm0, ymm0, ymm2
  146.   vaddpd ymm0, ymm0, ymm3
  147.  
  148.   vextractf128 xmm1, ymm0, 1
  149.   vaddpd xmm0, xmm0, xmm1
  150.   vhaddpd xmm0, xmm0, xmm0
  151.  
  152.   // Store result to C[i][j]
  153.   mov eax, edi
  154.   imul eax, MATRIX_SIZE
  155.   add eax, ebx
  156.   vmovsd [r12 + rax * 8], xmm0
  157.  
  158.   inc ebx
  159.   cmp ebx, MATRIX_SIZE
  160.   jl @middle_loop
  161.  
  162.   inc edi
  163.   jmp @outer_loop
  164.  
  165. @exit:
  166.   vzeroupper
  167.   pop rsi
  168.   pop rdi
  169.   pop r15
  170.   pop r14
  171.   pop r13
  172.   pop r12
  173.   pop rbx
  174.   xor eax, eax
  175. end;
  176. end;
  177. {------------------- Parallel AVX Multiplication ----------}
  178. procedure AVXMatrixMultParallel(a, b_transposed, c: PAlignDoubleArray);
  179. var
  180.   Threads: array of TThreadID = nil;
  181.   Data: array of TThreadData = nil;
  182.   i, rows_per_thread: Integer;
  183. begin
  184.   SetLength(Threads, THREAD_COUNT);
  185.   SetLength(Data, THREAD_COUNT);
  186.   rows_per_thread := MATRIX_SIZE div THREAD_COUNT;
  187.  
  188.   for i := 0 to THREAD_COUNT - 1 do
  189.   begin
  190.     Data[i].a := a;
  191.     Data[i].b_transposed := b_transposed;
  192.     Data[i].c := c;
  193.     Data[i].start_row := i * rows_per_thread;
  194.     Data[i].end_row := (i + 1) * rows_per_thread;
  195.     if i = THREAD_COUNT - 1 then
  196.       Data[i].end_row := MATRIX_SIZE;
  197.  
  198.     Threads[i] := BeginThread(@AVXThreadWorker, @Data[i]);
  199.   end;
  200.  
  201.   for i := 0 to THREAD_COUNT - 1 do
  202.     WaitForThreadTerminate(Threads[i], DWORD(INFINITE));
  203. end;
  204.  
  205.  
  206. {------------------- Naive Matrix Multiplication ---------}
  207. procedure NaiveMatrixMult(a, b, c: PAlignDoubleArray);
  208. var
  209.   i, j, k: Integer;
  210.   sum: Double;
  211. begin
  212.   for i := 0 to MATRIX_SIZE - 1 do
  213.     for j := 0 to MATRIX_SIZE - 1 do
  214.     begin
  215.       sum := 0;
  216.       for k := 0 to MATRIX_SIZE - 1 do
  217.         sum := sum + a^[i * MATRIX_SIZE + k] * b^[k * MATRIX_SIZE + j];
  218.       c^[i * MATRIX_SIZE + j] := sum;
  219.     end;
  220. end;
  221.  
  222. {------------------- Results Validation -------------------}
  223. procedure CheckResults(avx, naive: PAlignDoubleArray);
  224. var
  225.   i, j: Integer;
  226. begin
  227.   for i := 0 to MATRIX_SIZE - 1 do
  228.     for j := 0 to MATRIX_SIZE - 1 do
  229.       if Abs(avx^[i * MATRIX_SIZE + j] - naive^[i * MATRIX_SIZE + j]) > EPSILON then
  230.       begin
  231.         Writeln(Format('Error [%d,%d]: AVX=%.5f Naive=%.5f',
  232.           [i, j, avx^[i * MATRIX_SIZE + j], naive^[i * MATRIX_SIZE + j]]));
  233.         Exit;
  234.       end;
  235.   Writeln('Validation passed!');
  236. end;
  237.  
  238. {------------------- Main Program -------------------------}
  239.  
  240. var
  241.   i, j: Integer;
  242.   StartTime, EndTime: Int64;
  243.  
  244. begin
  245.   if not IsAVXSupported then
  246.   begin
  247.     Writeln('AVX not supported!');
  248.     Halt(1);
  249.   end;
  250.  
  251.   a := AlignedArrayAlloc(MATRIX_ELEMENTS);
  252.   b := AlignedArrayAlloc(MATRIX_ELEMENTS);
  253.   b_transposed := AlignedArrayAlloc(MATRIX_ELEMENTS);
  254.   c_avx := AlignedArrayAlloc(MATRIX_ELEMENTS);
  255.   c_naive := AlignedArrayAlloc(MATRIX_ELEMENTS);
  256.  
  257.   try
  258.     Randomize;
  259.     for i := 0 to MATRIX_SIZE - 1 do
  260.       for j := 0 to MATRIX_SIZE - 1 do
  261.       begin
  262.         a^[i * MATRIX_SIZE + j] := Random * 100;
  263.         b^[i * MATRIX_SIZE + j] := Random * 100;
  264.       end;
  265.  
  266.     TransposeMatrix(b, b_transposed);
  267.  
  268.     StartTime := GetTickCount64;
  269.     NaiveMatrixMult(a, b, c_naive);
  270.     EndTime := GetTickCount64;
  271.     Writeln('FPC Naive Execution Time, ms:         ', (EndTime - StartTime));
  272.  
  273.  
  274.     StartTime := GetTickCount64;
  275.     AVXMatrixMultParallel(a, b_transposed, c_avx);
  276.     EndTime := GetTickCount64;
  277.     Writeln('FPC AVX Execution Time, ms:           ', (EndTime - StartTime));
  278.  
  279.     CheckResults(c_avx, c_naive);
  280.  
  281.   finally
  282.     AlignedArrayFree(a);
  283.     AlignedArrayFree(b);
  284.     AlignedArrayFree(b_transposed);
  285.     AlignedArrayFree(c_avx);
  286.     AlignedArrayFree(c_naive);
  287.   end;
  288.   Readln;
  289. end.
  290.  

Output:

FPC Naive Execution Time, ms:         1390
FPC AVX Execution Time, ms:           32
Validation passed!

Final comparative results:

Code: Text  [Select][+][-]
  1. Fortran Execution Time, ms:        1140
  2. Cpp Execution Time, ms:            1433
  3. FPC Execution Time, ms:            2437
  4. FPC Naive Execution Time, ms:      1390
  5. FPC AVX Execution Time, ms:        32
  6.  
;D










440bx

  • Hero Member
  • *****
  • Posts: 5316
Re: Why isn't Lazarus / Free Pascal more popular?
« Reply #73 on: May 02, 2025, 10:31:50 pm »
If users really require inline variables to live then they should ask themselves whether a Pascal language is really the right choice for them. Inline variables have no place here.
I'm not a proponent of inline variables but, if they are not abused, they can definitely help in the writing of better code.  It's a feature I often miss.  I'm just not pleased with the Delphi (and C/C++) implementation.

The problem with Delphi's inline variables is that, begin/end really aren't good scope delimiters and, inline variables are much too easy to abuse but, they certainly help lower the number of variables that are global to a function/procedure.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v4.0rc3) on Windows 7 SP1 64bit.

JD

  • Hero Member
  • *****
  • Posts: 1905
Re: Why isn't Lazarus / Free Pascal more popular?
« Reply #74 on: May 02, 2025, 11:33:13 pm »
Okay, let's multiply two 1000x1000 matrices.

Well done! Personally, faced with this type of problem, I would just use GNU Octave or numpy but I get the point.  :D

JD
Linux Mint - Lazarus 4.0/FPC 3.2.2,
Windows - Lazarus 4.0/FPC 3.2.2

mORMot 2, PostgreSQL & MariaDB.

 

TinyPortal © 2005-2018