프런트엔드 고성능 컴퓨팅 공유 실현
프런트엔드 고성능 컴퓨팅 중 하나: WebWorkers WebWorkers란
간단히 말하면 WebWorkers는 HTML5의 새로운 API로, 웹 개발자는 이 API를 사용하여 UI를 차단하지 않고 백그라운드에서 스크립트를 실행할 수 있습니다. 필요한 작업을 수행하는 데 사용할 수 있습니다. 계산량이 많은 경우 여러 CPU 코어를 활용하세요.
기본적으로 모든 브라우저는 이제 WebWorkers를 지원합니다.
Parallel.js
WebWorkers 인터페이스를 직접 사용하는 것은 여전히 너무 번거롭습니다. 다행히도 누군가 Parallel.js로 이미 캡슐화했습니다.
Parallel.js는 node를 통해 설치할 수 있습니다.
$ npm install paralleljs
그러나 이는 node.js에서 node의 클러스터 모듈을 사용하여 사용됩니다. 브라우저에서 사용하려면 js를 직접 적용해야 합니다:
<script src="parallel.js"></script>
그런 다음 전역 변수인 Parallel을 얻을 수 있습니다. Parallel은 두 가지 기능적 프로그래밍 인터페이스인 map과 Reduce를 제공하여 동시 작업을 매우 편리하게 만듭니다.
먼저 문제를 정의해 보겠습니다. 사업이 상대적으로 복잡하기 때문에 여기서는 문제를 단순화하여 1~1,000,0000의 합을 구한 다음 1~1,000,0000을 차례로 빼겠습니다. 명백하다: 0 ! 숫자가 너무 크면 데이터 정확성에 문제가 생기고 두 방법의 결과가 다소 달라서 사람들이 병렬 방식을 신뢰할 수 없다고 느낄 수 있기 때문입니다. Mac pro chrome61에서 js를 직접 실행하면 이 문제는 약 1.5초가 걸립니다(실제 비즈니스 문제는 15초가 걸립니다. 사용자 테스트 중에 브라우저가 종료되는 것을 방지하기 위해 문제를 단순화했습니다).
const N = 100000000;// 总次数1亿 // 更新自2017-10-24 16:47:00 // 代码没有任何含义,纯粹是为了模拟一个耗时计算,直接用 // for (let i = start; i <= end; i += 1) total += i; // 有几个问题,一是代码太简单没有任何稍微复杂一点的操作,后面用C代码优化的时候会优化得很夸张,没法对比。 // 二是数据溢出问题, 我懒得处理这个问题,下面代码简单地先加起来,然后再减掉,答案显而易见为0,便于测试。 function sum(start, end) { let total = 0; for (let i = start; i <= end; i += 1) { if (i % 2 == 0 || i % 3 == 1) { total += i; } else if (i % 5 == 0 || i % 7 == 1) { total += i / 2; } } for (let i = start; i <= end; i += 1) { if (i % 2 == 0 || i % 3 == 1) { total -= i; } else if (i % 5 == 0 || i % 7 == 1) { total -= i / 2; } } return total; } function paraSum(N) { const N1 = N / 10;//我们分成10分,没分分别交给一个web worker,parallel.js会根据电脑的CPU核数建立适量的workers let p = new Parallel([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) .require(sum); return p.map(n => sum((n - 1) * 10000000 + 1, n * 10000000))// 在parallel.js里面没法直接应用外部变量N1 .reduce(data => { const acc = data[0]; const e = data[1]; return acc + e; }); } export { N, sum, paraSum }
코드는 비교적 간단합니다. 여기서는 처음 사용했을 때 겪었던 몇 가지 함정에 대해 이야기하겠습니다.
require all 필수 함수
예를 들어 sum이 어필 코드에 사용된다면 sum이 다른 함수 f를 사용하는 경우에도 require(f)를 미리 해야 합니다. if f g를 사용하는 경우 정의된 모든 함수가 사용되도록 요구할 때까지 require(g)도 필요합니다. . . .
변수를 요구할 수 없습니다
저희 어필 코드에는 원래 N1을 정의했는데 사용할 수 없었습니다
ES6를 ES5로 컴파일한 후 Chrome에서 오류가 보고되지 않는 문제
에서 실제 프로젝트에서는 처음에 ES6를 사용했습니다. 기능: 배열 구조 분해. 원래는 아주 간단한 기능이었지만 지금은 대부분의 브라우저에서 지원하지만, 당시 제가 구성한 바벨은 ES5로 컴파일이 되기 때문에 바벨로 온라인에서 테스트할 수는 없을 것입니다. Chrome에서 작동합니다. 오류 메시지가 없었습니다. 오랫동안 확인한 후 Firefox에서 열었더니
ReferenceError: _slicedToArray is not defined
Chrome이 전능하지 않은 것 같습니다. . .
이 데모 페이지에서 테스트할 수 있습니다. 물론 속도 증가는 컴퓨터 CPU의 코어 수에 따라 다릅니다. 또한 나중에 동일한 컴퓨터에서 Firefox 55.0.3(64비트)을 테스트했는데 실제로 항소 코드가 190ms밖에 걸리지 않았습니다! ! ! Safari9.1.1에서도 약 190ms입니다. . .
Refers
https://developer.mozilla.org/en/docs/Web/API/WebWorkersAPI/Usingwebworkers
https://www.html5rocks.com/en/tutorials/workers/basics/
https://parallel.js.org/
https://johnresig.com/blog/web-workers/
http://javascript.ruanyifeng.com/htmlapi/ webworker. html
http://blog.teamtreehouse.com/using-web-workers-to-speed-up-your-javascript-applications
프런트엔드 고성능 컴퓨팅 2부: asm.js & webassemble
앞서 고성능 컴퓨팅을 해결하는 두 가지 방법에 대해 이야기했는데, 하나는 WebWorkers를 동시에 사용하는 것이고, 다른 하나는 저수준 정적 언어를 사용하는 것입니다.
2012년 Mozilla 엔지니어 Alon Zakai는 LLVM 컴파일러를 연구하던 중 갑자기 아이디어를 얻었습니다. C/C++를 Javascript로 컴파일하여 네이티브 코드의 속도를 달성할 수 있을까? 그래서 그는 C/C++ 코드를 Javascript의 하위 집합인 asm.js로 컴파일하는 데 사용되는 Emscripten 컴파일러를 개발했습니다. 성능은 네이티브 코드의 거의 50%입니다. 이 PPT를 보시면 됩니다.
나중에 Google은 브라우저에서 C/C++ 코드를 실행할 수 있는 기술이기도 한 [Portable Native Client][PNaCI]를 개발했습니다. 나중에는 모두가 자신의 일을 하는 것이 불가능하다고 생각한 것 같습니다. 실제로 Google, Microsoft, Mozilla, Apple 및 기타 주요 회사가 협력하여 웹용 범용 바이너리 및 텍스트 형식 프로젝트를 개발했습니다. 공식 웹사이트는
Quote
WebAssembly 또는 wasm은 웹 컴파일에 적합한 새로운 이식 가능하고 크기 및 로드 시간 효율적인 형식입니다.
그래서 WebAssembly는 전망이 좋은 프로젝트여야 합니다. 현재 브라우저 지원을 살펴볼 수 있습니다:
Emscripten 설치
https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html
1을 방문하세요. 버전 SDK
2. emsdk
bash # Fetch the latest registry of available tools. ./emsdk update # Download and install the latest SDK tools. ./emsdk install latest # Make the "latest" SDK "active" for the current user. (writes ~/.emscripten file) ./emsdk activate latest # Activate PATH and other environment variables in the current terminal source ./emsdk_env.sh
3. 将下列添加到环境变量PATH中
~/emsdk-portable ~/emsdk-portable/clang/fastcomp/build_incoming_64/bin ~/emsdk-portable/emscripten/incoming
4. 其他
我在执行的时候碰到报错说LLVM版本不对,后来参考文档配置了LLVM_ROOT变量就好了,如果你没有遇到问题,可以忽略。
LLVM_ROOT = os.path.expanduser(os.getenv('LLVM', '/home/ubuntu/a-path/emscripten-fastcomp/build/bin'))
5. 验证是否安装好
执行emcc -v,如果安装好会出现如下信息:
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 1.37.21 clang version 4.0.0 (https://github.com/kripken/emscripten-fastcomp-clang.git 974b55fd84ca447c4297fc3b00cefb6394571d18) (https://github.com/kripken/emscripten-fastcomp.git 9e4ee9a67c3b67239bd1438e31263e2e86653db5) (emscripten 1.37.21 : 1.37.21) Target: x86_64-apple-darwin15.5.0 Thread model: posix InstalledDir: /Users/magicly/emsdk-portable/clang/fastcomp/build_incoming_64/bin INFO:root:(Emscripten: Running sanity checks)
Hello, WebAssembly!
创建一个文件hello.c:
#include <stdio.h> int main() { printf("Hello, WebAssembly!\n"); return 0; }
编译C/C++代码:
emcc hello.c
上述命令会生成一个a.out.js文件,我们可以直接用Node.js执行:
node a.out.js
输出:
Hello, WebAssembly!
为了让代码运行在网页里面,执行下面命令会生成hello.html和hello.js两个文件,其中hello.js和a.out.js内容是完全一样的。
emcc hello.c -o hello.html
➜ webasm-study md5 a.out.js MD5 (a.out.js) = d7397f44f817526a4d0f94bc85e46429 ➜ webasm-study md5 hello.js MD5 (hello.js) = d7397f44f817526a4d0f94bc85e46429
然后在浏览器打开hello.html,可以看到页面:;;
前面生成的代码都是asm.js,毕竟Emscripten是人家作者Alon Zakai最早用来生成asm.js的,默认输出asm.js也就不足为奇了。当然,可以通过option生成wasm,会生成三个文件:hello-wasm.html, hello-wasm.js, hello-wasm.wasm。
emcc hello.c -s WASM=1 -o hello-wasm.html
然后浏览器打开hello-wasm.html,发现报错TypeError: Failed to fetch。原因是wasm文件是通过XHR异步加载的,用file:////访问会报错,所以我们需要启一个服务器。
npm install -g serve serve .
然后访问http://localhost:5000/hello-wasm.html,就可以看到正常结果了。
调用C/C++函数
前面的Hello, WebAssembly!都是main函数直接打出来的,而我们使用WebAssembly的目的是为了高性能计算,做法多半是用C/C++实现某个函数进行耗时的计算,然后编译成wasm,暴露给js去调用。
在文件add.c中写如下代码:
#include <stdio.h> int add(int a, int b) { return a + b; } int main() { printf("a + b: %d", add(1, 2)); return 0; }
有两种方法可以把add方法暴露出来给js调用。
通过命令行参数暴露API
emcc -s EXPORTED_FUNCTIONS="['_add']" add.c -o add.js
注意方法名add前必须加_。 然后我们可以在Node.js里面这样使用:
// file node-add.js const add_module = require('./add.js'); console.log(add_module.ccall('add', 'number', ['number', 'number'], [2, 3]));
执行node node-add.js会输出5。如果需要在web页面使用的话,执行:
emcc -s EXPORTED_FUNCTIONS="['_add']" add.c -o add.html
然后在生成的add.html中加入如下代码:
<button onclick="nativeAdd()">click</button> <script type='text/javascript'> function nativeAdd() { const result = Module.ccall('add', 'number', ['number', 'number'], [2, 3]); alert(result); } </script>
然后点击button,就可以看到执行结果了。
Module.ccall会直接调用C/C++代码的方法,更通用的场景是我们获取到一个包装过的函数,可以在js里面反复调用,这需要用Module.cwrap,具体细节可以参看 文档 。
const cAdd = add_module.cwrap('add', 'number', ['number', 'number']); console.log(cAdd(2, 3)); console.log(cAdd(2, 4));
定义函数的时候添加EMSCRIPTEN_KEEPALIVE
添加文件add2.c。
#include <stdio.h> #include <emscripten.h> int EMSCRIPTEN_KEEPALIVE add(int a, int b) { return a + b; } int main() { printf("a + b: %d", add(1, 2)); return 0; }
执行命令:
emcc add2.c -o add2.html
同样在add2.html中添加代码:
<button onclick="nativeAdd()">click</button> <script type='text/javascript'> function nativeAdd() { const result = Module.ccall('add', 'number', ['number', 'number'], [2, 3]); alert(result); } </script>
但是,当你点击button的时候,报错:
Assertion failed: the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)
可以通过在main()中添加emscripten_exit_with_live_runtime()解决:
#include <stdio.h> #include <emscripten.h> int EMSCRIPTEN_KEEPALIVE add(int a, int b) { return a + b; } int main() { printf("a + b: %d", add(1, 2)); emscripten_exit_with_live_runtime(); return 0; }
或者也可以直接在命令行中添加-s NO_EXIT_RUNTIME=1来解决,
emcc add2.c -o add2.js -s NO_EXIT_RUNTIME=1
不过会报一个警告:
exit(0) implicitly called by end of main(), but noExitRuntime, so not exiting the runtime (you can use emscripten_force_exit, if you want to force a true shutdown)
所以建议采用第一种方法。
上述生成的代码都是asm.js,只需要在编译参数中添加-s WASM=1中就可以生成wasm,然后使用方法都一样。
用asm.js和WebAssembly执行耗时计算
前面准备工作都做完了, 现在我们来试一下用C代码来优化前一篇中提过的问题。代码很简单:
// file sum.c #include <stdio.h> // #include <emscripten.h> long sum(long start, long end) { long total = 0; for (long i = start; i <= end; i += 3) { total += i; } for (long i = start; i <= end; i += 3) { total -= i; } return total; } int main() { printf("sum(0, 1000000000): %ld", sum(0, 1000000000)); // emscripten_exit_with_live_runtime(); return 0; }
注意用gcc编译的时候需要把跟emscriten相关的两行代码注释掉,否则编译不过。 我们先直接用gcc编译成native code看看代码运行多块呢?
➜ webasm-study gcc sum.c ➜ webasm-study time ./a.out sum(0, 1000000000): 0./a.out 5.70s user 0.02s system 99% cpu 5.746 total ➜ webasm-study gcc -O1 sum.c ➜ webasm-study time ./a.out sum(0, 1000000000): 0./a.out 0.00s user 0.00s system 64% cpu 0.003 total ➜ webasm-study gcc -O2 sum.c ➜ webasm-study time ./a.out sum(0, 1000000000): 0./a.out 0.00s user 0.00s system 64% cpu 0.003 total
可以看到有没有优化差别还是很大的,优化过的代码执行时间是3ms!。really?仔细想想,我for循环了10亿次啊,每次for执行大概是两次加法,两次赋值,一次比较,而我总共做了两次for循环,也就是说至少是100亿次操作,而我的mac pro是2.5 GHz Intel Core i7,所以1s应该也就执行25亿次CPU指令操作吧,怎么可能逆天到这种程度,肯定是哪里错了。想起之前看到的 一篇rust测试性能的文章 ,说rust直接在编译的时候算出了答案, 然后把结果直接写到了编译出来的代码里, 不知道gcc是不是也做了类似的事情。在知乎上 GCC中-O1 -O2 -O3 优化的原理是什么? 这篇文章里, 还真有loop-invariant code motion(LICM)针对for的优化,所以我把代码增加了一些if判断,希望能“糊弄”得了gcc的优化。
#include <stdio.h> // #include <emscripten.h> // long EMSCRIPTEN_KEEPALIVE sum(long start, long end) { long sum(long start, long end) { long total = 0; for (long i = start; i <= end; i += 1) { if (i % 2 == 0 || i % 3 == 1) { total += i; } else if (i % 5 == 0 || i % 7 == 1) { total += i / 2; } } for (long i = start; i <= end; i += 1) { if (i % 2 == 0 || i % 3 == 1) { total -= i; } else if (i % 5 == 0 || i % 7 == 1) { total -= i / 2; } } return total; } int main() { printf("sum(0, 1000000000): %ld", sum(0, 100000000)); // emscripten_exit_with_live_runtime(); return 0; }
执行结果大概要正常一些了。
➜ webasm-study gcc -O2 sum.c ➜ webasm-study time ./a.out sum(0, 1000000000): 0./a.out 0.32s user 0.00s system 99% cpu 0.324 total
ok,我们来编译成asm.js了。
#include <stdio.h> #include <emscripten.h> long EMSCRIPTEN_KEEPALIVE sum(long start, long end) { // long sum(long start, long end) { long total = 0; for (long i = start; i <= end; i += 1) { if (i % 2 == 0 || i % 3 == 1) { total += i; } else if (i % 5 == 0 || i % 7 == 1) { total += i / 2; } } for (long i = start; i <= end; i += 1) { if (i % 2 == 0 || i % 3 == 1) { total -= i; } else if (i % 5 == 0 || i % 7 == 1) { total -= i / 2; } } return total; } int main() { printf("sum(0, 1000000000): %ld", sum(0, 100000000)); emscripten_exit_with_live_runtime(); return 0; }
执行:
emcc sum.c -o sum.html
然后在sum.html中添加代码
<button onclick="nativeSum()">NativeSum</button> <button onclick="jsSumCalc()">JSSum</button> <script type='text/javascript'> function nativeSum() { t1 = Date.now(); const result = Module.ccall('sum', 'number', ['number', 'number'], [0, 100000000]); t2 = Date.now(); console.log(`result: ${result}, cost time: ${t2 - t1}`); } </script> <script type='text/javascript'> function jsSum(start, end) { let total = 0; for (let i = start; i <= end; i += 1) { if (i % 2 == 0 || i % 3 == 1) { total += i; } else if (i % 5 == 0 || i % 7 == 1) { total += i / 2; } } for (let i = start; i <= end; i += 1) { if (i % 2 == 0 || i % 3 == 1) { total -= i; } else if (i % 5 == 0 || i % 7 == 1) { total -= i / 2; } } return total; } function jsSumCalc() { const N = 100000000;// 总次数1亿 t1 = Date.now(); result = jsSum(0, N); t2 = Date.now(); console.log(`result: ${result}, cost time: ${t2 - t1}`); } </script>
另外,我们修改成编译成WebAssembly看看效果呢?
emcc sum.c -o sum.js -s WASM=1
Browser | webassembly | asm.js | js |
Chrome61 | 1300ms | 600ms | 3300ms |
Firefox55 | 600ms | 800ms | 700ms |
Safari9.1 | 不支持 | 2800ms | 因不支持ES6我懒得改写没测试 |
感觉Firefox有点不合理啊, 默认的JS太强了吧。然后觉得webassembly也没有特别强啊,突然发现emcc编译的时候没有指定优化选项-O2。再来一次:
emcc -O2 sum.c -o sum.js # for asm.js emcc -O2 sum.c -o sum.js -s WASM=1 # for webassembly
Browser | webassembly -O2 | asm.js -O2 | js |
Chrome61 | 1300ms | 600ms | 3300ms |
Firefox55 | 650ms | 630ms | 700ms |
居然没什么变化, 大失所望。号称asm.js可以达到native的50%速度么,这个倒是好像达到了。但是今年 Compiling for the Web with WebAssembly (Google I/O '17) 里说WebAssembly是1.2x slower than native code,感觉不对呢。 asm.js 还有一个好处是,它就是js,所以即使浏览器不支持,也能当成不同的js执行,只是没有加速效果。当然 WebAssembly 受到各大厂商一致推崇,作为一个新的标准,肯定前景会更好,期待会有更好的表现。
Refers
人工智能是最近两年绝对的热点,而这次人工智能的复兴,有一个很重要的原因就是计算能力的提升,主要依赖于GPU。去年Nvidia的股价飙升了几倍,市面上好点的GPU一般都买不到,因为全被做深度学习以及挖比特币的人买光了
以上内容就是实现前端高性能计算分享,希望能帮助到大家。
相关推荐:
위 내용은 프런트엔드 고성능 컴퓨팅 공유 실현의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Quark Netdisk와 Baidu Netdisk는 매우 편리한 저장 도구입니다. 많은 사용자가 이 두 소프트웨어가 상호 운용 가능한지 묻고 있습니다. Quark Netdisk를 Baidu Netdisk에 공유하는 방법은 무엇입니까? 이 사이트에서는 Quark 네트워크 디스크 파일을 Baidu 네트워크 디스크에 저장하는 방법을 사용자에게 자세히 소개합니다. Quark Network Disk에서 Baidu Network Disk로 파일을 저장하는 방법 방법 1. Quark Network Disk에서 Baidu Network Disk로 파일을 전송하는 방법을 알고 싶다면 먼저 Quark Network Disk에 저장해야 하는 파일을 다운로드한 다음 엽니다. Baidu 네트워크 디스크 클라이언트에서 압축 파일을 저장할 폴더를 선택한 다음 두 번 클릭하여 폴더를 엽니다. 2. 폴더를 연 후 창 왼쪽 상단에 있는 "업로드"를 클릭하세요. 3. 컴퓨터에 업로드해야 하는 압축 파일을 찾아 클릭하여 선택합니다.

1. 먼저 NetEase Cloud Music에 들어간 다음 소프트웨어 홈페이지 인터페이스를 클릭하여 노래 재생 인터페이스로 들어갑니다. 2. 그런 다음 노래 재생 인터페이스에서 아래 그림의 빨간색 상자에 표시된 것처럼 오른쪽 상단에서 공유 기능 버튼을 찾아 공유 채널에서 공유 채널을 선택하고 다음 위치에서 "공유 대상" 옵션을 클릭합니다. 하단에서 첫 번째 "WeChat Moments"를 선택하면 WeChat Moments에 콘텐츠를 공유할 수 있습니다.

최근 Baidu Netdisk Android 클라이언트는 새로운 버전 8.0.0을 선보였습니다. 이 버전은 많은 변화를 가져올 뿐만 아니라 많은 실용적인 기능도 추가했습니다. 그 중 가장 눈길을 끄는 것은 폴더 공유 기능 강화다. 이제 사용자는 쉽게 친구를 초대하여 업무와 생활에서 중요한 파일을 공유하고 더욱 편리하게 협업하고 공유할 수 있습니다. 그렇다면 친구들과 공유해야 하는 파일을 어떻게 공유합니까? 아래에서 이 사이트의 편집자가 자세한 소개를 해줄 것입니다. 1) Baidu Cloud 앱을 열고 먼저 홈페이지에서 관련 폴더를 클릭한 다음 인터페이스 오른쪽 상단에 있는 [...] 아이콘을 클릭합니다(아래 참조). 2) 그런 다음에서 [+]를 클릭합니다. "공유 멤버" 열 ]을 선택하고 마지막으로 모두 확인합니다.

PHP와 Vue: 프론트엔드 개발 도구의 완벽한 조합 오늘날 인터넷이 빠르게 발전하는 시대에 프론트엔드 개발은 점점 더 중요해지고 있습니다. 사용자가 웹 사이트 및 애플리케이션 경험에 대한 요구 사항이 점점 더 높아짐에 따라 프런트 엔드 개발자는 보다 효율적이고 유연한 도구를 사용하여 반응형 및 대화형 인터페이스를 만들어야 합니다. 프론트엔드 개발 분야의 두 가지 중요한 기술인 PHP와 Vue.js는 함께 사용하면 완벽한 도구라고 볼 수 있습니다. 이 기사에서는 독자가 이 두 가지를 더 잘 이해하고 적용할 수 있도록 PHP와 Vue의 조합과 자세한 코드 예제를 살펴보겠습니다.

Mango TV에는 다양한 유형의 영화, TV 시리즈, 예능 프로그램 및 기타 리소스가 있으며 사용자는 자유롭게 선택하여 시청할 수 있습니다. Mango TV 회원은 모든 VIP 드라마를 시청할 수 있을 뿐만 아니라 사용자가 드라마를 즐겁게 시청할 수 있도록 최고 화질을 설정할 수 있습니다. 아래에서 편집자는 사용자가 사용하고 서둘러 살펴볼 수 있도록 무료 Mango TV 멤버십 계정을 제공합니다. 구경하다. Mango TV 최신 회원 계정 무료 공유 2023: 참고: 이것은 최근 수집된 회원 계정이며 로그인하여 직접 사용할 수 있으며 비밀번호를 마음대로 변경하지 마십시오. 계좌번호: 13842025699 비밀번호: qds373 계좌번호: 15804882888 비밀번호: evr6982 계좌번호: 13330925667 비밀번호: jgqae 계좌번호: 1703

프론트엔드 개발 인터뷰에서 일반적인 질문은 HTML/CSS 기초, JavaScript 기초, 프레임워크 및 라이브러리, 프로젝트 경험, 알고리즘 및 데이터 구조, 성능 최적화, 크로스 도메인 요청, 프론트엔드 엔지니어링, 디자인 패턴, 새로운 기술 및 트렌드. 면접관 질문은 후보자의 기술적 능력, 프로젝트 경험, 업계 동향에 대한 이해를 평가하기 위해 고안되었습니다. 따라서 지원자는 자신의 능력과 전문성을 입증할 수 있도록 해당 분야에 대한 충분한 준비를 갖추어야 합니다.

Django는 빠른 개발과 깔끔한 방법을 강조하는 Python으로 작성된 웹 애플리케이션 프레임워크입니다. Django는 웹 프레임워크이지만 Django가 프런트엔드인지 백엔드인지에 대한 질문에 답하려면 프런트엔드와 백엔드의 개념에 대한 깊은 이해가 필요합니다. 프론트엔드는 사용자가 직접 상호작용하는 인터페이스를 의미하고, 백엔드는 HTTP 프로토콜을 통해 데이터와 상호작용하는 서버측 프로그램을 의미합니다. 프론트엔드와 백엔드가 분리되면 프론트엔드와 백엔드 프로그램을 독립적으로 개발하여 각각 비즈니스 로직과 인터랙티브 효과, 데이터 교환을 구현할 수 있습니다.

HP 프린터는 많은 사무실에서 필수적인 인쇄 장비입니다. 컴퓨터에 프린터 드라이버를 설치하면 프린터가 연결되지 않는 등의 문제를 완벽하게 해결할 수 있습니다. 그렇다면 HP 프린터 드라이버를 설치하는 방법은 무엇입니까? 아래 편집기에서는 두 가지 HP 프린터 드라이버 설치 방법을 소개합니다. 첫 번째 방법: 공식 웹사이트에서 드라이버를 다운로드합니다. 1. 검색 엔진에서 HP China 공식 웹사이트를 검색하고 지원 열에서 [소프트웨어 및 드라이버]를 선택합니다. 2. [프린터] 카테고리를 선택하고 검색창에 프린터 모델을 입력한 후 [제출]을 클릭하여 프린터 드라이버를 찾으세요. 3. 컴퓨터 시스템에 따라 해당 프린터를 선택합니다. win10의 경우 win10 시스템용 드라이버를 선택합니다. 4. 다운로드가 성공적으로 완료되면 해당 폴더에서 찾아보세요.
