Perlin noise generation inefficiency

i’m trying to find a lot more efficient way to generate terrain using cubes
the issue is that every block that is created, it will use math.perlin() 24 times if i counted correctly
if there is any way to simplify the math that i did it would help, otherwise i can completely switch methods

local xSize = 64
local ySize = 256
local zSize = 64

local Ratio = 30
local MountainRatio = 180
local Amplitude = 5
local MountainAmplitude = 20

local Seed = math.random(100000000)
local MountainSeed = Seed + 500

local CubeFaces = {
	Vector3.new(1, 0, 0),
	Vector3.new(0, 1, 0),
	Vector3.new(0, 0, 1),
	Vector3.new(-1, 0, 0),
	Vector3.new(0, -1, 0),
	Vector3.new(0, 0, -1)
}

task.wait()

xSize /= 2
ySize /= 2
zSize /= 2

local function GetDensity(X, Y, Z)
	local MountainPerlin = -math.noise(X / MountainRatio, Z / MountainRatio, MountainSeed) * MountainAmplitude
	local xPerlin = math.noise(Y / Ratio, Z / Ratio, Seed) * Amplitude + MountainPerlin
	local yPerlin = math.noise(X / Ratio, Z / Ratio, Seed) * Amplitude + MountainPerlin
	local zPerlin = math.noise(X / Ratio, Y / Ratio, Seed) * Amplitude + MountainPerlin
	return xPerlin + yPerlin + zPerlin + Y
end

for X = -xSize, xSize do
	for Y = -ySize, ySize do
		for Z = -zSize, zSize do
			for xCheck = -1, 1 do
				for yCheck = -1, 1 do
					for zCheck = -1, 1 do
						if table.find(CubeFaces, Vector3.new(xCheck, yCheck, zCheck)) and GetDensity(X + xCheck, Y + yCheck, Z + zCheck) >= 0 then
							if GetDensity(X, Y, Z) < 0 then
								local Block = game.ReplicatedStorage.Blocks.Grass:Clone()
								Block.Position = Vector3.new(X, Y, Z) * 3
								Block.Parent = game.Workspace.World
							end
							break
						end
					end
				end
			end
		end
	end
	task.wait()
end