Học hỏi được rất nhiều.

 

Tất nhiên, phần so sánh phải là so sánh hiệu năng của hai hàm quickSort()quickSortInPlace()........

 

À.. tôi đã hiểu anh đang nói gì. Có vẻ anh đã không hiểu là cần phải so sánh cái gì với cái gì.... thuật toán quick sort không phải là có hai cách triển khai là quicksort và in-place đâu......

Ngay từ đầu, điều tôi xem là vấn đề chính là việc viết quickSortGPT()quickSort() trong đoạn mã trên — đều là mã do GPT tạo ra — với phần hợp nhất Array được tích hợp sẵn, rồi cung cấp chúng cho người dùng AI.

 

Chia sẻ kết quả cho thấy chênh lệch từ hơn gấp 2 đến tận 3~4 lần mà lại nói có vẻ không đến mức gấp 2 là sao?

 

Ngay cả bây giờ, khi phải làm việc cùng các lập trình viên ở độ tuổi 40-50, đôi lúc tôi cũng phát điên vì có những người cứ muốn phát triển theo cách họ đã làm từ vài chục năm trước, đúng là bó tay. Cá nhân tôi nghĩ rằng, giống như Nhật Bản, sẽ là một xã hội lành mạnh hơn nếu người trẻ có thể vào làm nhân viên chính thức thay vì chỉ làm thêm hay lao động không chính thức, còn người già thì chủ yếu làm các công việc thời vụ, bán thời gian. Ở Hàn Quốc, thu nhập từ lao động đang được phân chia theo kiểu kim tự tháp ngược, nên càng về sau tình trạng rút thang sau khi mình đã leo lên chỉ càng nghiêm trọng hơn.

 

Các nền tảng điều dưỡng kiểm tra tình trạng tín dụng của y tá thông qua các nhà môi giới dữ liệu, và khoản nợ càng nhiều thì mức lương được đề nghị càng thấp

Dữ liệu này được cung cấp bằng cách nào vậy?

 

Tôi đã tự chạy thử thì thấy có xu hướng chậm hơn một chút, nhưng có vẻ không đến mức gấp đôi.

function quickSortInPlace(arr, left = 0, right = arr.length - 1) {  
    if (left >= right) return;  
  
    const pivotIndex = partition(arr, left, right);  
    quickSortInPlace(arr, left, pivotIndex - 1);  
    quickSortInPlace(arr, pivotIndex + 1, right);  
}  
  
function partition(arr, left, right) {  
    const pivot = arr[right];  
    let i = left;  
  
    for (let j = left; j < right; j++) {  
        if (arr[j] < pivot) {  
            [arr[i], arr[j]] = [arr[j], arr[i]];  
            i++;  
        }  
    }  
  
    [arr[i], arr[right]] = [arr[right], arr[i]];  
    return i;  
}  
  
function quickSort(arr) {  
    if (arr.length <= 1) return arr;  
  
    const pivot = arr[arr.length - 1];  
    const left = [];  
    const right = [];  
  
    for (let i = 0; i < arr.length - 1; i++) {  
        if (arr[i] < pivot) {  
            left.push(arr[i]);  
        } else {  
            right.push(arr[i]);  
        }  
    }  
  
    return [...quickSort(left), pivot, ...quickSort(right)];  
}  
  
// =============  
  
function quickSortGPT(arr) {  
    if (!Array.isArray(arr)) {  
        throw new TypeError('quickSort expects an array');  
    }  
    if (arr.length <= 1) return [...arr];  
  
    const pivot = arr[Math.floor(arr.length / 2)];  
    const left = [];  
    const equal = [];  
    const right = [];  
  
    for (const el of arr) {  
        if (el < pivot) left.push(el);  
        else if (el > pivot) right.push(el);  
        else equal.push(el);  
    }  
  
    return [...quickSortGPT(left), ...equal, ...quickSortGPT(right)];  
}  
  
function quickSortInPlaceGPT(arr) {  
    if (!Array.isArray(arr)) {  
        throw new TypeError('quickSortInPlace expects an array');  
    }  
  
    const stack = [[0, arr.length - 1]];  
  
    while (stack.length) {  
        const [lo, hi] = stack.pop();  
        if (lo >= hi) continue;  
  
        const pivotIndex = partitionGPT(arr, lo, hi);  
  
        // Tail‑recursion elimination: push larger partition first  
        if (pivotIndex - 1 - lo > hi - (pivotIndex + 1)) {  
            stack.push([lo, pivotIndex - 1]);  
            stack.push([pivotIndex + 1, hi]);  
        } else {  
            stack.push([pivotIndex + 1, hi]);  
            stack.push([lo, pivotIndex - 1]);  
        }  
    }  
    return arr;  
}  
  
function medianOfThreeGPT(a, b, c) {  
    return (a - b) * (c - a) >= 0 ? a  
        : (b - a) * (c - b) >= 0 ? b  
            : c;  
}  
  
function partitionGPT(arr, lo, hi) {  
    const mid = lo + ((hi - lo) >> 1);  
    const pivotValue = medianOfThreeGPT(arr[lo], arr[mid], arr[hi]);  
  
    while (true) {  
        while (arr[lo] < pivotValue) lo++;  
        while (arr[hi] > pivotValue) hi--;  
  
        if (lo >= hi) return hi;  
  
        [arr[lo], arr[hi]] = [arr[hi], arr[lo]];  
        lo++;  
        hi--;  
    }  
}  
  
function testQuicksort(qs, qsp) {  
    const repeat = 100;  
    const arrLength = 100000;  
    const unsortedArray = new Array();  
    for (let i = 0; i < arrLength; i++)  
        unsortedArray.push(Math.round(Math.random() * arrLength));  
  
    let sorted = [];  
  
    const qb = performance.now();  
    for (let i = 0; i < repeat; i++)  
        sorted = qs(unsortedArray);  
    const qe = performance.now();  
  
    const rqb = performance.now();  
    for (let i = 0; i < repeat; i++) {  
        let copied = [...unsortedArray];  
        qsp(copied);  
    }  
    const rqe = performance.now();  
  
    // đến 2 chữ số thập phân  
    const p1 = ((qe - qb) / repeat).toFixed(2);  
    const p2 = ((rqe - rqb) / repeat).toFixed(2);  
    
    console.log(`Quicksort: ${p1} ms, In-place: ${p2} ms`);  
}  
  
function main() {  
    const useGPT = process.argv.includes('--gpt');  
    console.log(`Using ${useGPT ? 'GPT' : 'geekNews'} quicksort implementation.`);  
    if (useGPT) {  
        testQuicksort(quickSortGPT, quickSortInPlaceGPT);  
    } else {  
        testQuicksort(quickSort, quickSortInPlace);  
    }  
}  
  
main();  

===
node q.js
Using geekNews quicksort implementation.
Quicksort: 29.55 ms, In-place: 9.94 ms
node q.js
Using geekNews quicksort implementation.
Quicksort: 28.42 ms, In-place: 9.07 ms
node q.js
Using geekNews quicksort implementation.
Quicksort: 26.91 ms, In-place: 9.15 ms
node q.js --gpt
Using GPT quicksort implementation.
Quicksort: 28.73 ms, In-place: 9.22 ms
node q.js --gpt
Using GPT quicksort implementation.
Quicksort: 26.87 ms, In-place: 9.22 ms
node q.js --gpt
Using GPT quicksort implementation.
Quicksort: 27.97 ms, In-place: 9.30 ms
node --version
v22.14.0

bun q.js
Using geekNews quicksort implementation.
Quicksort: 32.05 ms, In-place: 17.39 ms
bun q.js
Using geekNews quicksort implementation.
Quicksort: 30.97 ms, In-place: 17.82 ms
bun q.js
Using geekNews quicksort implementation.
Quicksort: 29.73 ms, In-place: 16.14 ms
bun q.js --gpt
Using GPT quicksort implementation.
Quicksort: 30.61 ms, In-place: 12.63 ms
bun q.js --gpt
Using GPT quicksort implementation.
Quicksort: 31.09 ms, In-place: 12.76 ms
bun q.js --gpt
Using GPT quicksort implementation.
Quicksort: 33.24 ms, In-place: 12.75 ms
bun --version
1.2.14

deno q.js
Using geekNews quicksort implementation.
Quicksort: 32.30 ms, In-place: 6.79 ms
deno q.js
Using geekNews quicksort implementation.
Quicksort: 26.79 ms, In-place: 6.86 ms
deno q.js
Using geekNews quicksort implementation.
Quicksort: 26.09 ms, In-place: 6.85 ms
deno q.js --gpt
Using GPT quicksort implementation.
Quicksort: 27.18 ms, In-place: 7.92 ms
deno q.js --gpt
Using GPT quicksort implementation.
Quicksort: 25.34 ms, In-place: 8.12 ms
deno q.js --gpt
Using GPT quicksort implementation.
Quicksort: 25.39 ms, In-place: 8.09 ms
deno --version
deno 2.3.3 (stable, release, x86_64-pc-windows-msvc)
v8 13.7.152.6-rusty
typescript 5.8.3

 

Trước bài phát biểu đã có phần giới thiệu tài trợ từ Google và Facebook.

 

Cũng như câu “mất bò mới lo làm chuồng” không có nghĩa là đừng chuẩn bị cho tương lai,
thì theo tôi, câu “đừng phát minh lại bánh xe” cũng không có nghĩa là đừng đầu tư thời gian để có được insight.
Nếu cắt bỏ trước sau xem câu nói đó xuất hiện trong hoàn cảnh nào, ý nghĩa vốn có của nó sẽ bị bóp méo.

 
det7eng 2025-05-27 | bình luận cha | trong: Vì sao Mỹ luôn ghi nhận thâm hụt thương mại? (libertystreeteconomics.newyorkfed.org)

Tôi nghĩ đặc sản lớn nhất của Mỹ là đồng đô la

 

Khi cứ lặp đi lặp lại nhiều lần để giải quyết cùng một vấn đề thì sẽ vượt quá kích thước context window, và tôi đã nhiều lần gặp cảnh AI bị hỏng trong những lúc như vậy, nên cũng tò mò không biết những người khác xử lý trường hợp này thế nào.
Tôi thì khi thử nhiều lần mà nó vẫn hành xử ngớ ngẩn, sẽ đổi model và mở lại một cửa sổ prompt mới.

 

Đây là trải nghiệm gần đây của tôi, nhưng gần đây tôi đã tự tạo ra một chiếc bánh xe rất đặc biệt của riêng mình.
Việc build một ứng dụng Nuxt có 1000 trang mất 7 phút,
nhưng sau khi từ bỏ một vài phần tự động hóa và viết lại từ đầu, tôi đã thành công đưa thời gian build xuống còn 20 giây.

 

OSSU Open Source Society University - Tự học Computer Science

Có vẻ GeekNews đã từng giới thiệu từ khá sớm. Trong thời gian đó đã có thêm khá nhiều nội dung.

 

Cảm ơn vì câu trả lời!

 

quickSortInPlace() thứ hai mà bạn đính kèm cũng là một cách triển khai chậm.

Hãy thử chạy đoạn mã dưới đây.

function quickSortInPlace(arr, left = 0, right = arr.length - 1) {
if (left >= right) return;

const pivotIndex = partition(arr, left, right);
quickSortInPlace(arr, left, pivotIndex - 1);
quickSortInPlace(arr, pivotIndex + 1, right);
}

function partition(arr, left, right) {
const pivot = arr[right];
let i = left;

for (let j = left; j < right; j++) {
if (arr[j] < pivot) {
[arr[i], arr[j]] = [arr[j], arr[i]];
i++;
}
}

[arr[i], arr[right]] = [arr[right], arr[i]];
return i;
}

function quickSort(arr) {
if (arr.length <= 1) return arr;

const pivot = arr[arr.length - 1];
const left = [];
const right = [];

for (let i = 0; i < arr.length - 1; i++) {
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}

return [...quickSort(left), pivot, ...quickSort(right)];
}

const repeat = 100;
const arrLength = 10000;
const unsortedArray = new Array<number>();
for(let i = 0; i < arrLength; i++)
unsortedArray.push(Math.round(Math.random() * arrLength));

let sorted: Array<number>;

const qb = performance.now();
for(let i = 0; i < repeat; i++)
sorted = quickSort(unsortedArray);
const qe = performance.now();

const rqb = performance.now();
for(let i = 0; i < repeat; i++) {
let copied = [...unsortedArray];
quickSortInPlace(copied);
}
const rqe = performance.now();

console.log(q: ${qe - qb} ::: rq: ${rqe - rqb});

 

Đây là một bài viết mang lại cảm giác có chiều sâu lớn. Quả nhiên là a16z.

 

Thường thì tôi không hay viết bình luận, nhưng lý do tôi đặc biệt để lại bình luận cho bài này là vì tôi đồng cảm khá nhiều với suy nghĩ của tác giả. Tôi nghĩ điều quan trọng không phải là AI hay LLM, mà là với tư cách một lập trình viên, bản thân "tôi" phải luôn sẵn sàng dù môi trường nào có đến đi nữa.

Do đặc tính của mã nguồn đã được huấn luyện, LLM chủ yếu cung cấp dữ liệu nằm gần mức trung bình của dữ liệu trực tuyến trên toàn thế giới. (Ví dụ quicksort trong js trước đó đã chứng minh điều này.) Vì vậy, tôi thường dùng nó để hỏi xem về mặt tư tưởng/thiết kế thì nó có phần nào đồng điệu hay lệch khỏi góc nhìn phổ biến hay không, hoặc để hỏi những nội dung mà từ trước đến nay khá khó biết nên hỏi ai.

 

Tôi không rõ việc tiếp tục trao đổi thêm còn có ý nghĩa gì.

Ngay từ đầu, nếu ý kiến là mã do AI tạo ra có thể tiềm ẩn một số rủi ro, nên cần tinh chỉnh kỹ và sử dụng cho phù hợp, thì có lẽ chỉ cần giải thích xem trong bài viết của tác giả, suy nghĩ nào của tác giả là thiên lệch. Ngay cả trong bản tóm tắt cũng có câu mang ý tương tự: "có thể nhanh chóng cung cấp scaffold/mã nháp thiếu ngữ cảnh, nhưng thiết kế hoàn chỉnh và tinh chỉnh vẫn là phần việc của lập trình viên con người".

 

Về cơ bản, có thể xem đây là đoạn code hoàn toàn không đồng cảm với gánh nặng của việc tạo, vận hành và hợp nhất collection. Với C++, từ khoảng 10 năm trước đã có các đề xuất/triển khai về Move Constructor, và việc luôn cực kỳ nhạy cảm với chi phí sao chép bộ nhớ vốn là điều cơ bản nhất. Về mặt cơ chế, quick sort là thuật toán có thể xác định index của mọi giá trị, và tốt hơn là mỗi field nên hỗ trợ random access.

Ngay cả khi không có những tối ưu hóa kiểu "dị" mà chỉ áp dụng những điểm trên, hiệu năng cũng chênh hơn 2 lần so với cách ở link bạn gửi.