ਫ਼ੋਨ 'ਤੇ ਲਾਰਜ ਲੈਂਗੂਏਜ ਮਾਡਲ (LLMs) ਚਲਾਉਣਾ ਹੁਣ ਕੋਈ ਖੋਜ ਪ੍ਰਯੋਗ ਨਹੀਂ ਰਿਹਾ। ਇਹ ਇੱਕ ਅਸਲ ਹਕੀਕਤ ਬਣ ਚੁੱਕਾ ਹੈ। ਫਿਰ ਵੀ, ਜਿਵੇਂ ਹੀ ਤੁਸੀਂ ਇੱਕ ਟੋਏ ਡੈਮੋ (toy demo) ਤੋਂ ਅਸਲ ਉਤਪਾਦ ਵੱਲ ਵਧਦੇ ਹੋ, ਲੇਟੈਂਸੀ (latency) ਮੁੜ ਸਾਹਮਣੇ ਆ ਜਾਂਦੀ ਹੈ। ਤੁਸੀਂ ਮਾਡਲ ਨੂੰ ਛੋਟਾ ਕੀਤਾ, ਵੇਟਸ (weights) ਨੂੰ ਕਵਾਟਾਈਜ਼ (quantize) ਕੀਤਾ, ਫਿਰ ਵੀ ਪ੍ਰੀਫਿਲ ਫੇਜ਼ (prefill phase) ਲੰਬਾ ਖਿੱਚਦਾ ਹੈ। ਟੋਕਨ ਰੁਕ ਜਾਂਦੇ ਹਨ। UI ਫ੍ਰੀਜ਼ ਹੋ ਜਾਂਦੀ ਹੈ। ਦੋਸ਼ ਉੱਥੇ ਨਹੀਂ ਲੱਗਦਾ ਜਿੱਥੇ ਉਸਨੂੰ ਲੱਗਣਾ ਚਾਹੀਦਾ ਹੈ।

ਐਂਡਰਾਇਡ ਡਿਵਾਈਸਾਂ 'ਤੇ, LLM ਪ੍ਰੀਫਿਲ ਦੌਰਾਨ ਕੰਪਿਊਟ (compute) ਕਦੇ ਵੀ ਬੋਤਲਨੈਕ (bottleneck) ਨਹੀਂ ਹੁੰਦਾ। ਮੈਮੋਰੀ ਬੈਂਡਵਿਡਥ (memory bandwidth) ਹੁੰਦੀ ਹੈ। ਆਧੁਨਿਕ ਫਲੈਗਸ਼ਿਪ SoCs ਸ਼ਕਤੀਸ਼ਾਲੀ GPU ਅਤੇ NPU ਕੋਰਾਂ ਦੇ ਨਾਲ ਆਉਂਦੇ ਹਨ ਜੋ ਮੈਮੋਰੀ ਸਬਸਿਸਟਮ ਦੇ ਫੀਡ ਕਰਨ ਦੀ ਸਮਰੱਥਾ ਨਾਲੋਂ ਕਿਤੇ ਜ਼ਿਆਦਾ ਤੇਜ਼ੀ ਨਾਲ ਅਰਿਥਮੈਟਿਕ (arithmetic) ਕਰ ਸਕਦੇ ਹਨ। ਜਦੋਂ ਤੁਸੀਂ ਇੱਕ ਨਾਹੀਵ (naive) ਅਟੈਂਸ਼ਨ ਇੰਪਲੀਮੈਂਟੇਸ਼ਨ ਦਾ ਪ੍ਰੋਫਾਈਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਐਗਜ਼ੀਕਿਊਸ਼ਨ ਯੂਨਿਟਾਂ (execution units) ਦੀ ਸਮਰੱਥਾ ਪੂਰੀ ਨਹੀਂ ਵਰਤੀ ਜਾਂਦੀ। ਉਹ ਇੰਤਜ਼ਾਰ ਕਰ ਰਹੇ ਹੁੰਦੇ ਹਨ। DRAM ਦਾ ਇੰਤਜ਼ਾਰ ਕਰ ਰਹੇ ਹੁੰਦੇ ਹਨ।

ਤੁਹਾਡਾ ਕਵਾਟਾਈਜ਼ਡ ਮਾਡਲ ਅਜੇ ਵੀ ਹੌਲੀ ਕਿਉਂ ਮਹਿਸੂਸ ਹੁੰਦਾ ਹੈ

ਡਿਵਾਈਸ 'ਤੇ ਇਨਫਰੈਂਸ (inference) ਲਈ ਕਵਾਟਾਈਜ਼ੇਸ਼ਨ (quantization) ਡਿਫੌਲਟ ਪਹਿਲਾ ਕਦਮ ਬਣ ਗਿਆ ਹੈ। FP16 ਤੋਂ INT8 ਤੱਕ ਵੇਟਸ ਨੂੰ ਘਟਾਉਣ ਨਾਲ ਮਾਡਲ ਦਾ ਆਕਾਰ ਅੱਧਾ ਹੋ ਜਾਂਦਾ ਹੈ ਅਤੇ ਸਟੋਰੇਜ ਘਟ ਜਾਂਦੀ ਹੈ। ਇਹ ਮਦਦ ਕਰਦਾ ਹੈ। ਪਰ ਇਹ ਅਟੈਂਸ਼ਨ ਲੇਅਰ ਦੀ ਲੇਟੈਂਸੀ ਨੂੰ ਠੀਕ ਨਹੀਂ ਕਰਦਾ। ਕਾਰਨ ਸਧਾਰਨ ਹੈ: ਕਵਾਟਾਈਜ਼ੇਸ਼ਨ ਤੁਹਾਡੇ ਦੁਆਰਾ ਸਟੋਰ ਕੀਤੇ ਜਾਣ ਵਾਲੇ ਡੇਟਾ ਦੀ ਮਾਤਰਾ ਨੂੰ ਘਟਾਉਂਦੀ ਹੈ, ਪਰ ਇਹ ਮੈਮੋਰੀ ਟ੍ਰਾਂਜੈਕਸ਼ਨਾਂ (memory transactions) ਦੀ ਗਿਣਤੀ ਨੂੰ ਘੱਟ ਨਹੀਂ ਕਰਦੀ ਜੋ ਅਟੈਂਸ਼ਨ ਮਕੈਨਿਜ਼ਮ ਕਰਦਾ ਹੈ।

ਇੱਕ ਸਟੈਂਡਰਡ ਮਲਟੀ-ਹੈੱਡ ਅਟੈਂਸ਼ਨ ਲੇਅਰ, ਜਿਸ ਨੂੰ ਕਿਤਾਬੀ ਤਰੀਕੇ ਨਾਲ ਲਾਗੂ ਕੀਤਾ ਗਿਆ ਹੈ, ਹਰ ਲੇਅਰ ਲਈ DRAM ਤੱਕ ਤਿੰਨ ਪੂਰੇ ਰੇਂਡ ਟ੍ਰਿਪ (round trips) ਕਰਦੀ ਹੈ। Query, Key, ਅਤੇ Value ਮੈਟ੍ਰਿਕਸ ਨੂੰ ਮੇਨ ਮੈਮੋਰੀ ਤੋਂ ਪੜ੍ਹਿਆ ਜਾਂਦਾ ਹੈ, ਸਕੋਰਾਂ ਦੀ ਗਣਨਾ ਕੀਤੀ ਜਾਂਦੀ ਹੈ, ਅਤੇ ਵਿਚਕਾਰਲੇ ਨਤੀਜਿਆਂ ਨੂੰ ਵਾਪਸ ਲਿਖਿਆ ਜਾਂਦਾ ਹੈ। ਅਰਿਥਮੈਟਿਕ ਬਹੁਤ ਸੌਖਾ ਹੈ। ਡੇਟਾ ਦੀ ਹਰਕਤ ਬਹੁਤ ਜ਼ਿਆਦਾ ਹੈ। ਐਂਡਰਾਇਡ 'ਤੇ, ਜਿੱਥੇ ਪਾਵਰ ਅਤੇ ਥਰਮਲ ਬਜਟ ਸੀਮਤ ਹੁੰਦੇ ਹਨ, ਇਹ ਪੈਟਰਨ ਮੈਮੋਰੀ ਬੱਸ (memory bus) ਨੂੰ ਪ੍ਰਭਾਵਿਤ ਕਰਦਾ ਹੈ। ਪ੍ਰੋਸੈਸਰ ਅਸਲ ਵਿੱਚ ਇੱਕੋ ਪੁਲ ਨੂੰ ਪਾਰ ਕਰਨ ਲਈ ਤਿੰਨ ਵਾਰ ਟੋਲ (toll) ਦੇ ਰਿਹਾ ਹੈ।

ਜੇਕਰ ਤੁਸੀਂ INT8 ਮਾਡਲ ਸ਼ਿਪ ਕਰ ਰਹੇ ਹੋ ਅਤੇ ਸੋਚ ਰਹੇ ਹੋ ਕਿ ਪ੍ਰੀਫਿਲ ਸਟੈਪ ਅਜੇ ਵੀ ਪ੍ਰੋਂਪਟ ਲੰਬਾਈ ਦੇ ਨਾਲ ਕੁਆਡ੍ਰੈਟਿਕ (quadratically) ਤਰੀਕੇ ਨਾਲ ਕਿਉਂ ਵਧਦਾ ਹੈ, ਤਾਂ ਇਹ ਉਸਦਾ ਜਵਾਬ ਹੈ। ਵੇਟਸ ਛੋਟੇ ਹਨ, ਪਰ ਐਕਟੀਵੇਸ਼ਨ ਟ੍ਰੈਫਿਕ (activation traffic) ਅਜੇ ਵੀ ਬਹੁਤ ਜ਼ਿਆਦਾ ਹੈ।

ਬੋਤਲਨੈਕ ਮੈਮੋਰੀ ਹੈ, ਗਣਿਤ ਨਹੀਂ

ਸੁਧਾਰ ਨੂੰ ਸਮਝਣ ਲਈ, ਰੂਫਲਾਈਨ (roofline) ਵੱਲ ਦੇਖੋ। Snapdragon 8 Gen 3 ਅਤੇ Dimensity 9300 ਵਰਗੀਆਂ ਚਿੱਪਾਂ 'ਤੇ ਮੋਬਾਈਲ GPUs ਅਤੇ NPUs ਦੀ ਥਿਊਰੇਟੀਕਲ ਕੰਪਿਊਟ ਥਰੂਪੁੱਟ (theoretical compute throughput) ਉਹਨਾਂ ਦੇ LPDDR5X ਇੰਟਰਫੇਸਾਂ ਦੀ ਸਮਰੱਥਾ ਤੋਂ ਕਿਤੇ ਜ਼ਿਆਦਾ ਹੈ। ਇੱਕ ਨਾਹੀਵ ਅਟੈਂਸ਼ਨ ਕਰਨਲ (attention kernel) ਵਿੱਚ, ਹਰੇਕ ਹੈੱਡ Q ਅਤੇ K ਦੇ ਗੁਣਨਫਲ 'ਤੇ softmax ਦੀ ਗਣਨਾ ਕਰਦਾ ਹੈ, ਫਿਰ V ਨਾਲ ਗੁਣਾ ਕਰਦਾ ਹੈ। ਹਰ ਵਿਚਕਾਰਲਾ ਸਕੋਰ ਮੈਟ੍ਰਿਕਸ ਗਲੋਬਲ ਮੈਮੋਰੀ ਵਿੱਚ ਮਟੀਰੀਅਲਾਈਜ਼ (materialize) ਹੁੰਦਾ ਹੈ। ਇਸਦਾ ਮਤਲਬ ਹੈ ਕਿ ਤੁਹਾਡੇ ਪੀਕ DRAM ਰੀਡਸ (peak DRAM reads) ਸੀਕੁਐਂਸ ਲੰਬਾਈ ਦੇ ਵਰਗ, ਜਾਂ O(n²) ਦੇ ਅਨੁਪਾਤ ਵਿੱਚ ਵਧਦੇ ਹਨ। 1024-ਟੋਕਨ ਪ੍ਰੋਂਪਟ ਲਈ, ਮੈਮੋਰੀ ਟ੍ਰੈਫਿਕ ਪਹਿਲਾਂ ਹੀ ਐਗਜ਼ੀਕਿਊਸ਼ਨ ਸਮੇਂ 'ਤੇ ਹਾਵੀ ਹੋਣ ਲਈ ਕਾਫੀ ਵੱਡਾ ਹੈ।

ਕੋਰਾਂ ਦੀ ਵਰਤੋਂ ਘੱਟ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ ਕਿਉਂਕਿ ਉਹ ਲੇਟੈਂਸੀ ਨੂੰ ਛੁਪਾ ਨਹੀਂ ਸਕਦੇ। ਆਧੁਨਿਕ ਪ੍ਰੋਸੈਸਰ ਪਾਈਪਲਾਈਨਾਂ ਨੂੰ ਭਰਪੂਰ ਰੱਖਣ ਲਈ ਕੈਸ਼ (caches) 'ਤੇ ਨਿਰਭਰ ਕਰਦੇ ਹਨ। ਜਦੋਂ ਕੋਈ ਐਲਗੋਰਿਦਮ ਲਗਾਤਾਰ ਕੈਸ਼ ਵਿੱਚ ਮਿਸ ਹੁੰਦਾ ਹੈ ਅਤੇ DRAM ਤੋਂ ਡੇਟਾ ਲੈਂਦਾ ਹੈ, ਤਾਂ