NS3學習——tcpVegas算法代碼詳解(2)

NS3學習——tcpVegas算法代碼詳解(1)-CSDN博客

目錄

4.TcpVegas類中成員函數

(5) CongestionStateSet函數

(6)?IncreaseWindow函數

1.檢查是否啟用 Vgas

2.判斷是否完成了一個“Vegas 周期”

2.1--if:判斷RTT樣本數量是否足夠

2.2--else:RTT 樣本 > 2

2.2.1 if--diff > m_gamma 并且處于慢啟動階段

2.2.2 else if--?diff <?m_gamma 并且處于慢啟動階段

2.2.3 else-- 進入擁塞避免階段

2.2.3.1 --if?diff > m_beta

2.2.3.2?--else if?diff < m_alpha?

2.2.3.3?--else ?m_alpha < diff < m_beta

2.2.4 --更新慢開始閾值

?2.3 --重置RTT計數與最小RTT

3.慢啟動階段判斷

(7) GetName函數

(8) GetSsThresh函數


4.TcpVegas類中成員函數

(5) CongestionStateSet函數

void
TcpVegas::CongestionStateSet (Ptr<TcpSocketState> tcb,const TcpSocketState::TcpCongState_t newState)
{NS_LOG_FUNCTION (this << tcb << newState);if (newState == TcpSocketState::CA_OPEN){EnableVegas (tcb);}else{DisableVegas ();}
}

函數作用:根據TCP連接的擁塞狀態來啟用或者禁用Vegas算法。

函數體:檢查傳入的newState 參數值是否為:TcpSocketState::CA_OPEN(擁塞避免階段),若是,則啟用Vegas算法,TCP使用該算法來調整擁塞窗口的值;若不是,則停止使用Vegas。

TcpVegas 算法通常在擁塞避免階段啟用,因為此時網絡已穩定,Vegas 可以通過動態調整擁塞窗口來更好地利用網絡帶寬,并避免網絡擁塞。

(6)?IncreaseWindow函數

void
TcpVegas::IncreaseWindow (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked)
{NS_LOG_FUNCTION (this << tcb << segmentsAcked);if (!m_doingVegasNow){NS_LOG_LOGIC ("Vegas is not turned on, we follow NewReno algorithm.");TcpNewReno::IncreaseWindow (tcb, segmentsAcked);return;}if (tcb->m_lastAckedSeq >= m_begSndNxt){ // A Vegas cycle has finished, we do Vegas cwnd adjustment every RTT.NS_LOG_LOGIC ("A Vegas cycle has finished, we adjust cwnd once per RTT.");m_begSndNxt = tcb->m_nextTxSequence;if (m_cntRtt <= 2){  // We do not have enough RTT samples, so we should behave like RenoNS_LOG_LOGIC ("We do not have enough RTT samples to do Vegas, so we behave like NewReno.");TcpNewReno::IncreaseWindow (tcb, segmentsAcked);}else //m_cntRtt > 2{NS_LOG_LOGIC ("We have enough RTT samples to perform Vegas calculations");uint32_t diff;uint32_t targetCwnd;uint32_t segCwnd = tcb->GetCwndInSegments ();double tmp = m_baseRtt.GetSeconds () / m_minRtt.GetSeconds ();targetCwnd = static_cast<uint32_t> (segCwnd * tmp);NS_LOG_DEBUG ("Calculated targetCwnd = " << targetCwnd);NS_ASSERT (segCwnd >= targetCwnd); // implies baseRtt <= minRttdiff = segCwnd - targetCwnd;NS_LOG_DEBUG ("Calculated diff = " << diff);if (diff > m_gamma && (tcb->m_cWnd < tcb->m_ssThresh)){NS_LOG_LOGIC ("We are going too fast. We need to slow down and ""change to linear increase/decrease mode.");segCwnd = std::min (segCwnd, targetCwnd + 1);tcb->m_cWnd = segCwnd * tcb->m_segmentSize;tcb->m_ssThresh = GetSsThresh (tcb, 0);NS_LOG_DEBUG ("Updated cwnd = " << tcb->m_cWnd <<" ssthresh=" << tcb->m_ssThresh);}else if (tcb->m_cWnd < tcb->m_ssThresh){     // Slow start modeNS_LOG_LOGIC ("We are in slow start and diff < m_gamma, so we ""follow NewReno slow start");TcpNewReno::SlowStart (tcb, segmentsAcked);}else //tcb m_cWnd > m_ssThresh{     // Linear increase/decrease modeNS_LOG_LOGIC ("We are in linear increase/decrease mode");if (diff > m_beta){NS_LOG_LOGIC ("We are going too fast, so we slow down by decrementing cwnd");segCwnd--;tcb->m_cWnd = segCwnd * tcb->m_segmentSize;tcb->m_ssThresh = GetSsThresh (tcb, 0);NS_LOG_DEBUG ("Updated cwnd = " << tcb->m_cWnd <<" ssthresh=" << tcb->m_ssThresh);}else if (diff < m_alpha){NS_LOG_LOGIC ("We are going too slow, so we speed up by incrementing cwnd");segCwnd++;tcb->m_cWnd = segCwnd * tcb->m_segmentSize;NS_LOG_DEBUG ("Updated cwnd = " << tcb->m_cWnd <<" ssthresh=" << tcb->m_ssThresh);}else //   m_alpha < diff < m_beta{NS_LOG_LOGIC ("We are sending at the right speed");}} //else  tcb m_cWnd > m_ssThreshtcb->m_ssThresh = std::max (tcb->m_ssThresh, 3 * tcb->m_cWnd / 4);NS_LOG_DEBUG ("Updated ssThresh = " << tcb->m_ssThresh);} // else m_cntRtt > 2m_cntRtt = 0;m_minRtt = Time::Max ();} //if tcb->m_lastAckedSeq >= m_begSndNxtelse if (tcb->m_cWnd < tcb->m_ssThresh)  //tcb->m_lastAckedSeq < m_begSndNxt{TcpNewReno::SlowStart (tcb, segmentsAcked);}
} //IncreaseWindow

函數體邏輯:

1.檢查是否啟用 Vgas

if (!m_doingVegasNow)
{// If Vegas is not on, we follow NewReno algorithmNS_LOG_LOGIC ("Vegas is not turned on, we follow NewReno algorithm.");TcpNewReno::IncreaseWindow (tcb, segmentsAcked);return;
}

如果 m_doingVegasNow 為 false,即 Vegas 算法沒有啟用,那么執行?NewReno 擁塞控制算法。如果 Vegas 啟用,那么執行以下代碼:

2.判斷是否完成了一個“Vegas 周期”

if (tcb->m_lastAckedSeq >= m_begSndNxt)
{// A Vegas cycle has finished, we do Vegas cwnd adjustment every RTT.NS_LOG_LOGIC ("A Vegas cycle has finished, we adjust cwnd once per RTT.");m_begSndNxt = tcb->m_nextTxSequence;

如果?tcb->m_lastAckedSeq發送方成功接收到的最后一個已確認包的序列號)大于等于 m_begSndNxt(?Vegas 周期開始時的發送序列號),則表示當前已經完成了一個 Vegas 周期,并且將 m_begSndNxt 更新為當前的 tcb->m_nextTxSequence,以便下次周期開始時使用新的序列號。執行以下代碼:

補:在 Vegas 算法中,一個周期是指發送方根據當前 RTT(往返時延)計算并調整其擁塞窗口(cwnd)的過程。這個周期通常與 RTT 周期同步。

m_lastAckedSeq 的變化非常重要,它幫助判斷一個周期是否已經完成。每當接收方成功確認一個數據包,m_lastAckedSeq 會更新,以便發送方能知道哪些數據包已經被接收并得到確認。

在每個周期開始時,m_begSndNxt 會被更新為 當前發送序列號,而這個序列號代表的是 下一個將要發送的數據包的起始字節序列號。
當接收到的 ACK 包的序列號大于等于 m_begSndNxt 時,說明當前周期的所有數據包已經被確認,當前周期結束。

每個周期(每個 RTT)執行一次 IncreaseWindow。

tcb->m_nextTxSequence 是當前即將發送的下一個數據包的序列號。將 m_begSndNxt 更新為 tcb->m_nextTxSequence 是為了確保下一個周期從正確的地方開始。

2.1--if:判斷RTT樣本數量是否足夠
if (m_cntRtt <= 2)
{// We do not have enough RTT samples, so we should behave like RenoNS_LOG_LOGIC ("We do not have enough RTT samples to do Vegas, so we behave like NewReno.");TcpNewReno::IncreaseWindow (tcb, segmentsAcked);
}

Vegas 需要足夠的 RTT 樣本才能做出可靠的擁塞窗口調整。

如果 RTT 樣本數少于 2(即 m_cntRtt <= 2),它會退回到 NewReno 行為,這時會使用一個簡單的慢啟動和擁塞避免機制。

如果 RTT 樣本 > 2,算法就會根據 Vegas 的邏輯調整cwnd值,同時執行else中的代碼:

2.2--else:RTT 樣本 > 2
else
{NS_LOG_LOGIC ("We have enough RTT samples to perform Vegas calculations");

計算目標擁塞窗口:

uint32_t diff;
uint32_t targetCwnd;
uint32_t segCwnd = tcb->GetCwndInSegments ();double tmp = m_baseRtt.GetSeconds () / m_minRtt.GetSeconds ();
targetCwnd = static_cast<uint32_t> (segCwnd * tmp);
NS_LOG_DEBUG ("Calculated targetCwnd = " << targetCwnd);
NS_ASSERT (segCwnd >= targetCwnd); // implies baseRtt <= minRtt

Vegas 計算目標擁塞窗口(targetCwnd),首先獲取當前擁塞窗口大小 segCwnd,然后根據 baseRtt(最小 RTT)和 minRtt(當前窗口內最小 RTT)來計算目標擁塞窗口。

如果 baseRtt 小于等于 minRtt,就可以安全計算目標窗口。

NS_ASSERT (segCwnd >= targetCwnd);

計算公式如下:??

targetCwnd=segCwnd*\frac{baseRtt}{minRtt}

計算實際擁塞窗口與目標窗口的差值:

diff = segCwnd - targetCwnd;
NS_LOG_DEBUG ("Calculated diff = " << diff);

?計算當前擁塞窗口與目標擁塞窗口之間的差值 diff。這個差值會決定是否需要調整擁塞窗口的大小。

2.2.1 if--diff > m_gamma 并且處于慢啟動階段

當前窗口的差值 diff 大于閾值 m_gamma,并且當前處于慢啟動階段(cwnd 小于 m_ssThresh)

if (diff > m_gamma && (tcb->m_cWnd < tcb->m_ssThresh))
{// We are going too fast. We need to slow down and change from// slow-start to linear increase/decrease mode by setting cwnd// to target cwnd. We add 1 because of the integer truncation.NS_LOG_LOGIC ("We are going too fast. We need to slow down and ""change to linear increase/decrease mode.");segCwnd = std::min (segCwnd, targetCwnd + 1);tcb->m_cWnd = segCwnd * tcb->m_segmentSize;tcb->m_ssThresh = GetSsThresh (tcb, 0);NS_LOG_DEBUG ("Updated cwnd = " << tcb->m_cWnd << " ssthresh=" << tcb->m_ssThresh);
}

m_alpha 和 m_beta 用于在正常的增速和減速中控制窗口的變化。m_gamma 是一個更大的閾值,通常用于判斷網絡是否發生了擁塞。

如果 diff > m_gamma,說明當前發送速率比目標速率快得多,且當前處于慢啟動階段。在慢啟動階段,cwnd 會急劇增長。如果在慢啟動階段的擁塞窗口已大于目標值,說明網絡可能出現了擁塞的風險。

segCwnd = std::min(segCwnd, targetCwnd + 1):

調整當前cwnd,防止 segCwnd 超過目標窗口 targetCwnd,即避免發送方繼續過快地發送數據。

由于 segCwnd 是以“段”為單位的(tcb->GetCwndInSegments()),加1的操作是為了避免整數截斷。因為在計算過程中,通常會有一個小數部分,而加 1 可以保證計算結果向上取整,避免由于整數取整帶來的問題。

比如,如果目標擁塞窗口是 targetCwnd = 5.4,由于取整的原因,segCwnd 可能被調整為 5,而加 1 后調整為 6。這樣可以確保窗口不會太小,從而避免過早減速。

tcb->m_cWnd = segCwnd * tcb->m_segmentSize:

segCwnd 是擁塞窗口的大小(以段為單位)。
tcb->m_segmentSize 是每個 TCP 數據段的大小(字節數)。
segCwnd * tcb->m_segmentSize 得到的是字節級別的擁塞窗口大小,即實際可發送的數據量(以字節為單位)。通過這個公式,可以將段數(segCwnd)轉換為字節數(tcb->m_cWnd),并調整發送窗口。

tcb->m_ssThresh = GetSsThresh(tcb, 0):

重新計算并設置新的慢啟動閾值,用于控制從慢啟動到擁塞避免階段的過渡。

2.2.2 else if--?diff <?m_gamma 并且處于慢啟動階段

當前的擁塞窗口小于慢啟動閾值 m_ssThresh 并且?diff 小于?m_gamma

else if (tcb->m_cWnd < tcb->m_ssThresh)
{// Slow start modeNS_LOG_LOGIC ("We are in slow start and diff < m_gamma, so we ""follow NewReno slow start");TcpNewReno::SlowStart (tcb, segmentsAcked);
}

如果當前的擁塞窗口小于慢啟動閾值 m_ssThresh,說明此時處于慢啟動階段。此時 diff 小于 m_gamma,表明網絡沒有擁塞,擁塞窗口仍然可以增長。

此時退回使用 NewReno 算法中的慢啟動階段,通過調用 TcpNewReno::SlowStart 來增加擁塞窗口。

2.2.3 else-- 進入擁塞避免階段

當前的擁塞窗口大于慢啟動閾值,tcb->m_cWnd 大于或等于 tcb->m_ssThresh

進入擁塞避免階段,通過與目標 targetCwnd 的差值 diff 大小來選擇是 增加窗口、減小窗口,還是 保持當前窗口。

else
{// Linear increase/decrease modeNS_LOG_LOGIC ("We are in linear increase/decrease mode");
2.2.3.1 --if?diff > m_beta
if (diff > m_beta){// We are going too fast, so we slow downNS_LOG_LOGIC ("We are going too fast, so we slow down by decrementing cwnd");segCwnd--;tcb->m_cWnd = segCwnd * tcb->m_segmentSize;tcb->m_ssThresh = GetSsThresh (tcb, 0);NS_LOG_DEBUG ("Updated cwnd = " << tcb->m_cWnd << " ssthresh=" << tcb->m_ssThresh);}
  • 這表示當前發送速率太快,實際的發送速率(segCwnd)已經超過了目標速率 targetCwnd。
  • 為了避免擁塞,減小 segCwnd,即減小擁塞窗口,從而減慢發送速率。
  • 減小后的 segCwnd 通過 tcb->m_cWnd = segCwnd * tcb->m_segmentSize; 更新。
  • 同時, 通過 GetSsThresh(tcb, 0) 更新慢啟動閾值 tcb->m_ssThresh。
2.2.3.2?--else if?diff < m_alpha?
 else if (diff < m_alpha){// We are going too slow, so we speed upNS_LOG_LOGIC ("We are going too slow, so we speed up by incrementing cwnd");segCwnd++;tcb->m_cWnd = segCwnd * tcb->m_segmentSize;NS_LOG_DEBUG ("Updated cwnd = " << tcb->m_cWnd << " ssthresh=" << tcb->m_ssThresh);}
  • 這表示 當前發送速率太慢,實際的發送速率(segCwnd)低于目標速率 targetCwnd。
  • 為了加速數據傳輸,增加 segCwnd,即增大 擁塞窗口。
  • 增大的 segCwnd 同樣通過 tcb->m_cWnd = segCwnd * tcb->m_segmentSize; 更新。
  • 在這種情況下,不需要調整慢啟動閾值 tcb->m_ssThresh,因為它不會影響這一階段的行為。
2.2.3.3?--else ?m_alpha < diff < m_beta
else 
{NS_LOG_LOGIC ("We are sending at the right speed");
}
  • 這表示 當前發送速率合適,既不太快也不太慢,數據流量保持在理想狀態。
  • 不需要對擁塞窗口做出調整,繼續維持當前的速率。
2.2.4 --更新慢開始閾值
tcb->m_ssThresh = std::max (tcb->m_ssThresh, 3 * tcb->m_cWnd / 4);
NS_LOG_DEBUG ("Updated ssThresh = " << tcb->m_ssThresh);
  • 在(根據擁塞窗口和慢啟動閾值大小比較)進行窗口調整之后,根據當前的擁塞窗口 tcb->m_cWnd 更新慢啟動閾值(ssthresh)。
  • 計算公式 3 * tcb->m_cWnd / 4 是根據 Vegas 算法的設定,確保慢啟動閾值不會過小。
  • 最終tcb->m_ssThresh 會被設置為 tcb->m_ssThresh 和 3 * tcb->m_cWnd / 4 中的較大值。這是為了確保慢啟動閾值有足夠的大小,避免在后續過程中頻繁進入慢啟動階段。
?2.3 --重置RTT計數與最小RTT
m_cntRtt = 0;
m_minRtt = Time::Max ();
  • 由于每個周期結束都會重新進行 RTT 測量和窗口調整,所以需要重置 RTT計數(m_cntRtt)和最小RTT(m_minRtt)值。
  • m_cntRtt = 0:重置 RTT 樣本計數器。
  • m_minRtt = Time::Max():將最小 RTT 重置為一個很大的值,確保下一周期開始時能夠重新計算最小 RTT。

3.慢啟動階段判斷

else if (tcb->m_cWnd < tcb->m_ssThresh)
{TcpNewReno::SlowStart(tcb, segmentsAcked);
}

在周期結束后,檢查是否進入了慢啟動階段:

如果當前擁塞窗口 cwnd 小于慢啟動閾值 ssThresh,則執行 NewReno 的慢啟動算法,快速增長窗口。

注:如果tcb->m_lastAckedSeq < m_begSndNxt,表示當前 Vegas 周期沒有結束,那么會進入 else if 判斷,如果滿足慢啟動條件(tcb->m_cWnd < tcb->m_ssThresh),則會執行 NewReno 的慢啟動算法。

為什么最后還要判斷是否進入慢開始階段?

如果 cwnd 小于 ssthresh,本應處于慢啟動階段,但由于沒有判斷 cwnd < ssthresh,程序會直接進入其他模式(如線性增加階段)。這意味著即使 cwnd 還處于慢啟動階段,程序也會讓它變得增長更慢。由于此時 cwnd 還較小,采用線性增長的方式會導致窗口增長太慢,無法迅速利用帶寬,從而導致 網絡利用率低,吞吐量上升的速度很慢,甚至不能充分利用網絡的帶寬。也就是說,可能會在不該進入線性增長階段時就進入該階段,從而導致 窗口增長速度過慢,降低網絡利用率。

這個判斷確保了在每個階段執行適當的窗口調整策略,并幫助算法正確地處理不同網絡狀態下的擁塞控制。

(7) GetName函數

std::string
TcpVegas::GetName () const
{return "TcpVegas";
}

此函數主要用于標識 TCP 擁塞控制算法的類型,通過調用 GetName(),程序可以知道當前正在使用的是 TCP Vegas 算法。返回一個字符串,"TcpVegas"。

(8) GetSsThresh函數

uint32_t
TcpVegas::GetSsThresh (Ptr<const TcpSocketState> tcb,uint32_t bytesInFlight)
{NS_LOG_FUNCTION (this << tcb << bytesInFlight);return std::max (std::min (tcb->m_ssThresh.Get (), tcb->m_cWnd.Get () - tcb->m_segmentSize), 2 * tcb->m_segmentSize);
}} // namespace ns3

該函數的作用是計算和返回慢啟動閾值(ssthresh)。

Ptr<const TcpSocketState>,指向當前連接的 TCP 套接字狀態。TcpSocketState 中存儲了關于當前 TCP 連接的許多信息,如擁塞窗口(m_cWnd)、慢啟動閾值(m_ssThresh)等。
bytesInFlight:這通常表示當前已發送但尚未確認的數據量。這個參數在此函數中沒有被直接使用。

tcb->m_ssThresh.Get():當前連接的慢啟動閾值。
tcb->m_cWnd.Get() - tcb->m_segmentSize:計算擁塞窗口(cwnd)減去一個數據段的大小,表示如果當前 cwnd 足夠大時,應該將 ssthresh 設置為接近這個值。
2 * tcb->m_segmentSize:這是 ssthresh 的最小值,表示即使擁塞窗口較小時,慢啟動閾值也不會低于 2 * m_segmentSize。這個值是一個合理的下限,避免在擁塞窗口很小的時候,ssthresh 過小導致性能問題。

返回值:該函數通過 std::max() 和 std::min() 保證返回的 ssthresh 在合理的范圍內:

std::min():確保 ssthresh 不會大于 cwnd - segmentSize,即不能超過當前擁塞窗口減去一個數據段的大小。
std::max():確保 ssthresh 不會小于 2 * segmentSize,即在任何情況下 ssthresh 至少為兩個數據段大小。
最終返回值就是經過限制的 ssthresh,這是擁塞控制中切換模式的關鍵值。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/64146.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/64146.shtml
英文地址,請注明出處:http://en.pswp.cn/web/64146.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

GitLab 將停止為中國區用戶提供服務,60天遷移期如何應對? | LeetTalk Daily

“LeetTalk Daily”&#xff0c;每日科技前沿&#xff0c;由LeetTools AI精心篩選&#xff0c;為您帶來最新鮮、最具洞察力的科技新聞。 GitLab作為一個廣受歡迎的開源代碼托管平臺&#xff0c;近期宣布將停止服務中國大陸、澳門和香港地區的用戶提供服務。根據官方通知&#x…

華為實訓課筆記 2024 1223-1224

華為實訓 12/2312/24 12/23 [Huawei]stp enable --開啟STP display stp brief --查詢STP MSTID Port Role STP State Protection 實例ID 端口 端口角色 端口狀態 是否開啟保護[Huawei]display stp vlan xxxx --查詢制定vlan的生成樹計算結…

企業數字化轉型中如何區分“IT投入”和“業務投入”

在數字化轉型的浪潮中&#xff0c;企業往往面臨一個關鍵問題&#xff1a;如何區分“IT投入”和“業務投入”&#xff1f;在很多企業中&#xff0c;這兩個概念往往被混淆&#xff0c;不少公司甚至認為“數字化轉型”就是“IT的事情”&#xff0c;但實際上&#xff0c;它們之間有…

【Spring AI】Spring AI Alibaba的簡單使用

提示&#xff1a;文章最后有詳細的參考文檔。 前提條件 SpringBoot版本為3.x以上JDK為17以上申請api-key&#xff0c;地址&#xff1a;百煉平臺 引入依賴 說明&#xff1a;我的springboot版本為3.2.4&#xff0c;spring-ai-alibaba-starter版本為1.0.0-M2.1(對應spring-ai版本…

《Java源力物語》-3.空值獵手

~犬&#x1f4f0;余~ “我欲賤而貴&#xff0c;愚而智&#xff0c;貧而富&#xff0c;可乎&#xff1f; 曰&#xff1a;其唯學乎” \quad 夜色漸深&#xff0c;在一處偏僻小徑上&#xff0c;月光透過濃密的源力云層&#xff0c;在地面上投下斑駁的光影。String正獨自練習著剛從…

科技云報到:人工智能時代“三大件”:生成式AI、數據、云服務

科技云報到原創。 就像自行車、手表和縫紉機是工業時代的“三大件”。生成式AI、數據、云服務正在成為智能時代的“新三大件”。加之全球人工智能新基建加速建設&#xff0c;成為了人類社會數字化遷徙的助推劑&#xff0c;讓新三大件之間的耦合越來越緊密。從物理世界到數字世…

hiprint結合vue2項目實現靜默打印詳細使用步驟

代碼地址是&#xff1a;vue-plugin-hiprint: hiprint for Vue2/Vue3 ?打印、打印設計、可視化設計器、報表設計、元素編輯、可視化打印編輯 本地安裝包地址&#xff1a;electron-hiprint 發行版 - Gitee.com 1、先安裝hipint安裝包在本地 2、項目運行npm&#xff08;socket.…

CUDA各種內存和使用方法

文章目錄 1、全局內存2、局部內存3、共享內存3.1 靜態共享內存3.2 動態共享內存 4、紋理內存5、常量內存6、寄存器內存7、用CUDA運行時API函數查詢設備CUDA 錯誤檢測 1、全局內存 特點&#xff1a;容量最大&#xff0c;訪問延時最大&#xff0c;所有線程都可以訪問。 線性內存…

Chapter 03 復合數據類型-1

1.列表 Python內置的一種有序、可變的序列數據類型&#xff1b; 列表的定義&#xff1a; [ ]括起來的逗號分隔的多個元素組成的序列 列表對象的創建&#xff1a; &#xff08;1&#xff09;直接賦值 >>> list1 []#創建一個空列表賦值給list1 >>> list…

【后端】LNMP環境搭建

長期更新各種好文&#xff0c;建議關注收藏&#xff01; 本文近期更新完畢。 LNMPlinuxnginxmysqlphp 需要的資源 linux服務器 web服務軟件nginx 對應的語言編譯器代碼文件 數據庫mysql安裝 tar.gz包或者命令行安裝 進入root&#xff1a; sodu 或su mkdir path/{server,soft}…

基于PyQt5的UI界面開發——多界面切換

介紹 最初&#xff0c;因為課設的緣故&#xff0c;我只是想做一個通過按鍵進行切面切換而已&#xff0c;但是我看網上資料里面僅是語焉不詳&#xff0c;讓我困惑的很&#xff0c;但后面我通過摸索才發現這件事實在是太簡單了&#xff0c;因此我想要記錄下來。 本博客將介紹如…

操作002:HelloWorld

文章目錄 操作002&#xff1a;HelloWorld一、目標二、具體操作1、創建Java工程①消息發送端&#xff08;生產者&#xff09;②消息接收端&#xff08;消費者&#xff09;③添加依賴 2、發送消息①Java代碼②查看效果 3、接收消息①Java代碼②控制臺打印③查看后臺管理界面 操作…

機器視覺檢測相機基礎知識 | 顏色 | 光源 | 鏡頭 | 分辨率 / 精度 / 公差

注&#xff1a;本文為 “keyence 視覺沙龍中機器視覺檢測基礎知識” 文章合輯。 機器視覺檢測基礎知識&#xff08;一&#xff09;顏色篇 視覺檢測硬件構成的基本部分包括&#xff1a;處理器、相機、鏡頭、光源。 其中&#xff0c;和光源相關的最重要的兩個參數就是光源顏色和…

【每日學點鴻蒙知識】壓力測試、Web組件攔截器、nfc開關狀態、定位能力、rn支持的三方庫

1、HarmonyOS的wukong 支持運行python腳本進行壓力或者常規測試嗎&#xff1f; Python腳本調用hdc命令&#xff0c;執行hdc shell wukong XXXwukong只支持穩定性壓測&#xff0c;普通測試建議使用arkxtest測試框架 2、Web組件頁面內跳轉時自定義WebHeader問題&#xff1f; 如…

GDPU Vue前端框架開發 期末賽道出勇士篇(更新ing)

記住&#xff0c;年底陪你跨年的不會僅是方便面跟你的閨蜜&#xff0c;還有孑的筆記。 選擇題 1.下列選項用于設置Vue.js頁面視圖的元素是&#xff08;&#xff09;。 A. Template B. script C. style D. title 2.下列選項中能夠定義Vuejs根實例對象的元素是&#xff08;&…

Flutter開發HarmonyOS 鴻蒙App的好處、能力以及把Flutter項目打包成鴻蒙應用

Flutter開發HarmonyOS的好處&#xff1a; Flutter是谷歌公司開發的一款開源、免費的UI框架&#xff0c;可以讓我們快速的在Android和iOS上構建高質量App。它最大的特點就是跨平臺、以及高性能。 目前 Flutter 已經支持 iOS、Android、Web、Windows、macOS、Linux 的跨平臺開發…

Effective C++ 條款 17:以獨立語句將 `newed` 對象置入智能指針

文章目錄 條款 17&#xff1a;以獨立語句將 newed 對象置入智能指針核心思想示例代碼錯誤用法分析推薦設計總結 條款 17&#xff1a;以獨立語句將 newed 對象置入智能指針 核心思想 問題背景 如果在將 newed 對象傳遞給智能指針時&#xff0c;包含了復雜的表達式&#xff0c;一…

【體驗官招募】SoFlu - JavaAI 開發助手:開啟智能開發新時代

你是否有過這樣的經歷&#xff1f;在深夜的辦公室里&#xff0c;面對緊急的 Java 項目&#xff0c;看著厚厚的需求文檔&#xff0c;你是否感到無從下手&#xff1f; 當你嘗試理解客戶那些復雜又模糊的需求時&#xff0c;是否會因為要和產品經理反復溝通確認每一個細節而感到厭…

【Compose multiplatform教程07】多平臺常用組件和重要組件目錄

一、基礎交互與顯示組件 Text 查看示例 功能說明&#xff1a;用于在界面上顯示文本內容&#xff0c;支持設置字體、大小、顏色、樣式&#xff08;如加粗、斜體、下劃線&#xff09;等屬性&#xff0c;滿足不同的文本展示需求&#xff0c;可傳達各種信息給用戶。示例場景&#…

自學記錄HarmonyOS Next DRM API 13:構建安全的數字內容保護系統

在完成了HarmonyOS Camera API的開發之后&#xff0c;我開始關注更復雜的系統級功能。在瀏覽HarmonyOS Next文檔時&#xff0c;我發現了一個非常有趣的領域&#xff1a;數字版權管理&#xff08;DRM&#xff09;。最新的DRM API 13提供了強大的工具&#xff0c;用于保護數字內容…