<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      python進(jìn)程 - 調(diào)試報(bào)錯(cuò) you are not using fork to start your child processes

      在走這段代碼的時(shí)候報(bào)錯(cuò)了,記錄一下我的調(diào)試過(guò)程,感覺(jué)有個(gè)思路來(lái)走就挺好的。

      • 1、報(bào)錯(cuò)與解決

      文件名字:ClassifierTest.py

      import torch
      import torchvision
      import torchvision.transforms as transforms
      from torchTest import imgShow
      
      transform = transforms.Compose([transforms.ToTensor(),
                                      transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
      trainset = torchvision.datasets.CIFAR10(root='Resources/CIFAR10',  # 存放路徑 #?。?Resources/CIFAR10是絕對(duì)路徑,C:\Resources\CIFAR10
                                          train=True, download=True,  # 是否下載訓(xùn)練集
                                          transform=transform)  # 圖片轉(zhuǎn)換
      trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2)
      testset = torchvision.datasets.CIFAR10(root='Resources/CIFAR10', train=False, download=True, transform=transform)
      testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=2)
      
      classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
      
      dataIter = iter(trainloader)
      images, labels = dataIter.next()
      imgShow.imshow(torchvision.utils.make_grid(images))
      print(' '.join(classes[labels[j]] for j in range(4)))

      報(bào)錯(cuò)

              This probably means that you are not using fork to start your
              child processes and you have forgotten to use the proper idiom
              in the main module:

                  if __name__ == '__main__':
                      freeze_support()
                      ...

              The "freeze_support()" line can be omitted if the program
              is not going to be frozen to produce an executable.

      關(guān)于這個(gè)報(bào)錯(cuò),涉及線程問(wèn)題,改num_workers=0,當(dāng)然就么事沒(méi)有,然而,作為一個(gè)優(yōu)秀的程序員,能止步于此嗎,不行的。

      我百度了一下報(bào)錯(cuò)情況,找到這樣的解決方案,是可行:

      def main():
          transform = transforms.Compose([transforms.ToTensor(),
                                          transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
          trainset = torchvision.datasets.CIFAR10(root='Resources/CIFAR10',  # 存放路徑,注:/Resources/CIFAR10是絕對(duì)路徑,C:\Resources\CIFAR10
                                                  train=True, download=True,  # 是否下載訓(xùn)練集
                                                  transform=transform)  # 圖片轉(zhuǎn)換
          trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2)
          testset = torchvision.datasets.CIFAR10(root='Resources/CIFAR10', train=False, download=True, transform=transform)
          testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=2)
          classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
      
          dataIter = iter(trainloader)
          images, labels = dataIter.next()
          imgShow.imshow(torchvision.utils.make_grid(images))
          print(' '.join(classes[labels[j]] for j in range(4)))
      
      if __name__=='__main__': #不加這句就會(huì)報(bào)錯(cuò)
          main()

       

      • 2、為什么是main?

      整段放在main里面,就安全了——為什么呢?

      對(duì)于python編程我還是萌新,實(shí)在想不明白加個(gè)__name__=='__main__'判斷有什么魅力。

      關(guān)于__name__屬性:

      作為啟動(dòng)腳本,它模塊的__name__都是__main__。

      此句主要作用在于有時(shí)候import,不想運(yùn)行引用模塊中某些語(yǔ)句的時(shí)候,以啟動(dòng)模塊的名字作為區(qū)別。

      報(bào)錯(cuò)的位置在這里:

      C:\Users\13723\AppData\Local\Programs\Python\Python39\Lib\multiprocessing\spawn.py

      def _check_not_importing_main():
          if getattr(process.current_process(), '_inheriting', False):
              raise RuntimeError('''
              An attempt has been made to start a new process before the
              current process has finished its bootstrapping phase...''')

      getattr(實(shí)例, 屬性名字, 默認(rèn)值)

      如果有屬性,取True,否則取默認(rèn)值,沒(méi)有默認(rèn)值則取False。

      _inheriting,查找當(dāng)前程序的可繼承性?沒(méi)用過(guò),筆者不知道呢。

      看不懂(下文有解),只能從方法名字入手,它走這一段為了什么——

      檢查是不是源自__main__模塊,即程序不讓由執(zhí)行腳本import的模塊走這一段。

       

      我跑ClassifierTest.py(進(jìn)程pid1),它在走到

      dataIter = iter(trainloader)

      里面,由其他模塊,再導(dǎo)入了一次ClassifierTest.py(此時(shí)是進(jìn)程pid2)

      而當(dāng)增加判斷 __name__==’__main__’,就避免模塊陷入執(zhí)行的死循環(huán)。

       

      • 3、為什么多一個(gè)進(jìn)程?

      3.1 現(xiàn)象

      為什么會(huì)多一個(gè)進(jìn)程,num_workers=2,此句是一個(gè)進(jìn)程兩個(gè)線程worker,還是兩個(gè)進(jìn)程worker呢?

       我很奇怪,為什么不是開(kāi)線程,而是開(kāi)進(jìn)程這么個(gè)重量級(jí)東西。

      雖然叫做process,但它應(yīng)該只干一個(gè)事情——畢竟進(jìn)程的重量級(jí)要大于線程。

       

      3.2 線程與進(jìn)程

      這個(gè)時(shí)候就很糾結(jié)線程和進(jìn)程的區(qū)別了,

      (參考:https://www.zhihu.com/question/25532384

      線程是cpu執(zhí)行的時(shí)間段顆粒,

      進(jìn)程保存上下文,cpu切進(jìn)進(jìn)程里面讀取上下文(寄存器、指令內(nèi)容之類(lèi))。

      這樣看來(lái),如果進(jìn)程是倉(cāng)庫(kù),線程就是倉(cāng)庫(kù)里面的機(jī)器人,等待CPU來(lái)靈魂激活。但是在一個(gè)倉(cāng)庫(kù)里面工作,必然比在多個(gè)倉(cāng)庫(kù)里面工作要省事。

      所以為什么要開(kāi)多進(jìn)程呢?

      一個(gè)莫名的靈感,讓我查了一下fork(),

      (參考:http://www.rzrgm.cn/liyuan989/p/4279210.html

      因?yàn)檫M(jìn)程、線程是windows系統(tǒng)的概念,unix中只有進(jìn)程的說(shuō)法。

      在windows當(dāng)中,進(jìn)程是資源管理的最小單位,而線程是程序執(zhí)行的最小單位。

      fork創(chuàng)建的一個(gè)子進(jìn)程幾乎但不完全與父進(jìn)程相同。

      子進(jìn)程得到與父進(jìn)程用戶(hù)級(jí)虛擬地址空間相同的(但是獨(dú)立的)一份拷貝,

      包括文本、數(shù)據(jù)和bss段、堆以及用戶(hù)棧等。

      子進(jìn)程還獲得與父進(jìn)程任何打開(kāi)文件描述符相同的拷貝,

      這就意味著子進(jìn)程可以讀寫(xiě)父進(jìn)程中任何打開(kāi)的文件,父進(jìn)程和子進(jìn)程區(qū)別在于它們有著不同的PID。

       fork 意為分支,分支與父進(jìn)程幾乎一樣的子進(jìn)程。子進(jìn)程區(qū)別于父進(jìn)程,兩者有不同的pid,但二者的引用均指向相同的地址。

       

      話(huà)雖如此,Python里面確實(shí)是包含threading,和process模塊,那為什么選擇process更好?

      (參考:https://zhuanlan.zhihu.com/p/20953544)

      一個(gè)進(jìn)程,有一個(gè)全局鎖GIL(Global Interpreter Lock),此設(shè)定是為了數(shù)據(jù)安全。

      線程執(zhí)行時(shí),先獲取GIL,執(zhí)行代碼直到sleep或掛起,釋放GIL。

      所以多線程執(zhí)行,其實(shí)僅是宏觀時(shí)間上處理多任務(wù),微觀時(shí)間上仍是順序處理。

      而每個(gè)進(jìn)程有各自獨(dú)立的GIL,互不干擾,多進(jìn)程才能在真正意義上實(shí)現(xiàn)并行執(zhí)行(多核CPU同時(shí)做多個(gè)任務(wù),程序在微觀時(shí)間上同時(shí)執(zhí)行)。

       

      3.3 Python中,worker是進(jìn)程

      為什么會(huì)再讀一次ClassifierTest.py,從堆棧看,是這里:

      (注,以下截圖可能取自不同次調(diào)試,所以父pid會(huì)不同)

       走了 exec(code, run_globals) 導(dǎo)致再此導(dǎo)入 ClassifierTest.py 。

      再往前走frame not available,也即IDE只能看到spawn_main函數(shù)。

      (spawn應(yīng)該就是孵化了,孵化進(jìn)程的,還挺有蛇下蛋的感覺(jué))

       更之前的調(diào)用情況沒(méi)有了,可以猜是不是新進(jìn)程直接調(diào)用spawn_main了,那就找spawn_main引用。

      (可能pyCharm我還沒(méi)get靈魂用法,spawn_main引用我是用notepad++查找全局的)

      Python39\Lib\multiprocessing\popen_spawn_win32.py

       

      前后呼應(yīng):

      在查看堆棧的過(guò)程中,恰巧看到了_inheriting的賦值:

      堆棧可以看到對(duì)_inheriting賦值,此時(shí)就很明了表示是否子進(jìn)程,此處賦值True。

      再者,inheriting是ing結(jié)尾,表示進(jìn)行時(shí)狀態(tài);如果是表示繼承性,應(yīng)該叫inherited,如此看來(lái)這個(gè)編程就很細(xì)心,自己寫(xiě)程序的時(shí)候也得注意。

       

       3.4 num_workers=2 的結(jié)果

      前文設(shè)置num_workers = 2,此時(shí)就是父進(jìn)程帶著兩個(gè)子進(jìn)程,

      __name__==’__main__’ 的處理,阻止了子進(jìn)程由于調(diào)用 ClassifierTest.py 而再生子子進(jìn)程的子孫無(wú)窮盡也。

       

      主線程12012 它有兩個(gè)worker,分別是 15480 和 7036 。

      (這個(gè)數(shù)值是系統(tǒng)分配的pid編號(hào),區(qū)分進(jìn)程的代號(hào),每次啟動(dòng)程序都不同)

      15480 和 7036 帶著自己的Queue,dataloader.py完成了這個(gè)配置。

      dataIter = iter(trainloader)
      images, labels = dataIter.next()

      當(dāng)執(zhí)行 next(),程序會(huì)讀取象 dataIter 當(dāng)中的 _data_queue ,這個(gè)數(shù)據(jù)由兩個(gè)子進(jìn)程各自傳入。

      data = self._data_queue.get(timeout=timeout)

       具體實(shí)現(xiàn)看這個(gè)類(lèi):

      C:\Users\13723\PycharmProjects\pythonProject\venv\Lib\site-packages\torch\utils\data\dataloader.py

      class _MultiProcessingDataLoaderIter(_BaseDataLoaderIter):
      pass

       

      • 4、結(jié)語(yǔ)

        由一個(gè)小小的報(bào)錯(cuò),能“查漏補(bǔ)缺”知識(shí)漏洞就挺好的,鍛煉思維也挺好的。共勉。

       

      posted @ 2021-07-30 00:24  Carcar019  閱讀(6018)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 中文字幕无码视频手机免费看| 欧美亚洲国产精品久久| 国内精品免费久久久久电影院97 | 国产成人无码一区二区三区| 久久精品国产亚洲av麻豆软件| 好男人日本社区www| 国产精品高清国产三级囯产AV| 久久亚洲精品中文字幕波多野结衣| 久久爱在线视频在线观看| 两个人看的www免费视频中文| 人人妻人人澡人人爽| 99热精品毛片全部国产无缓冲| 欧美成人片一区二区三区| 男女啪啪网站| 给我中国免费播放片在线| 美女爽到高潮嗷嗷嗷叫免费网站| 中文在线天堂中文在线天堂| www射我里面在线观看| 99在线国内在线视频22| 亚洲国产精品日韩专区av| 日日噜噜噜夜夜爽爽狠狠视频| 亚洲天堂男人的天堂在线| 国产97视频人人做人人爱| 中文字幕av无码免费一区| 免费可以在线看a∨网站| 制服丝袜国产精品| 狠狠色丁香婷婷综合尤物| 99精品国产中文字幕| 鹰潭市| 国内熟妇与亚洲洲熟妇妇| 一区二区三区鲁丝不卡| 国产在线一区二区不卡| 91青青草视频在线观看| 野花社区www视频日本| 云霄县| 欧美激烈精交gif动态图| 欧美视频网站www色| 日韩中文字幕亚洲精品一| 中国女人熟毛茸茸A毛片| 亚洲岛国av一区二区| 国内久久人妻风流av免费|