简体   繁体   English

使用多线程优化硬盘上的读取/写入功能的速度

[英]Optimizing speed of read/write function on hard disk using multithreading

I am trying to read -> encrypt/decrypt -> write raw data on volumes sector by sector. 我正在尝试读取->加密/解密->逐扇区在卷上写入原始数据。 I need to optimize the time somehow because it is taking more than 2 hours for a volume of mere 2GB (my volume G: here). 我需要以某种方式优化时间,因为仅2GB的容量(我的容量G:在这里)要花费两个多小时。 I tried using threads to handle the time problem but it had no significant results. 我尝试使用线程来处理时间问题,但是没有明显的结果。 The program needs to run on a everyday use PC. 该程序需要在日常使用的PC上运行。

Each Thread operates on a different block of sectors from the other threads. 每个线程与其他线程在不同的扇区块上运行。

Things I know: 我知道的事情:

  1. Read cannot be done while writing (So I handled the critical section problem) 写入时无法完成读取(因此我处理了关键部分的问题)
  2. Read/Write in threads decreases time because of the seek time etc. 线程中的读/写由于查找时间等原因而减少了时间。
  3. Too many threads might fail to accomplish the task due to the latency ( caused by the read/write head moving back and forth. (gives error DEVICE_NOT_READY)) 由于延迟(由读写头来回移动引起的线程过多,可能无法完成任务。(给出错误DEVICE_NOT_READY))

Want I want to ask: 我想问一下:

  1. Can I utilize threads to write-read or write-write on two different sectors simultaneously (because I know that the disk operations are carried out using scheduling algorithms answered here )? 我是否可以利用线程同时在两个不同的扇区上进行读写操作(因为我知道磁盘操作是使用此处回答的调度算法执行的)?
  2. Why program generates the error when while during write in one thread (on one sector), the other threads tries to read (on another sector)? 为什么当在一个线程(在一个扇区中)上进行写操作时,其他线程试图在另一个扇区(上扇区)上进行读操作时,程序会生成错误?
  3. What modifications would you suggest to bring down the time? 您建议进行哪些修改以减少时间?

Code: 码:

DWORD WINAPI EncryptSectorBlock(LPVOID lpParam)
{
    PTARGS args = (PTARGS)lpParam;
    static unsigned char buffer[SECTOR_SIZE];

    printf("Thread No:%i start:%i  end:%i\n ", args->thread_id, args->sector_start, args->sector_end);

    for (int i = args->sector_start; i <= args->sector_end; i++)
    {
        //Entering critical section of the code. The Other Threads Would be first spin with 65536 loops and then set to
        // sleep until the worker threads releases the lock on critical section

        if (ReadSector(args->read, buffer, SECTOR_SIZE, i) != 1)
            printf("Thread: %i. Error reading sector %i\n",args->thread_id, i);
        else
            printf("Thread: %i. Read Sector %i Successfully\n", args->thread_id, i);

        xts_encrypt_sector(buffer, i, SECTOR_SIZE, &(args->ctx));

        //Critical Section starts
        EnterCriticalSection(&CriticalSection);
        if (WriteSector(args->write, buffer, SECTOR_SIZE, i) != 1)
            printf("Thread: %i. Error writing sector %i\n",args->thread_id ,i);
        else
            printf("Thread: %i. Wrote Sector %i Successfully\n", args->thread_id, i);
        //Critical Section Ends
        LeaveCriticalSection(&CriticalSection);


        //init to zero every time in case a sector is failed to be read or write, so it can recover from fault 
        //This may break in future.. Not proper mechanism to recover from   fault. just a hack.
         memset(buffer, 0, SECTOR_SIZE);
    }
    return 0;
  }

INT_RETURN EncryptFullVolume(wchar_t* volume, unsigned char* key)
{   
       //init variables here

            for (int i = 0; i < MAX_Threads; i++)
        {
            ArgsDataArray[i] = (PTARGS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TARGS));

            if (ArgsDataArray[i] == NULL)
            {
                // If the array allocation fails, the system is out of memory
                // so there is no point in trying to print an error message.
                // Just terminate execution.
                ret = EXIT_FAILURE;
            }
            else
            {
                // Generate unique data for each thread to work with here

               // Create the thread to begin execution on its own.
                hThreadArray[i] = CreateThread(
                    NULL,                   // default security attributes
                    0,                      // use default stack size  
                    EncryptSectorBlock,     // thread function name
                    ArgsDataArray[i],          // argument to thread function 
                    0,                      // use default creation flags 
                    &ThreadIdArray[i]);   // returns the thread identifier 

                if (hThreadArray[i] == NULL)
                {
                    ret = EXIT_FAILURE;
                }

                sector_offset += sectors_per_thread;
            }

        } // End of main thread creation loop.

            // Wait until all threads have terminated.

        DWORD result = WaitForMultipleObjects(MAX_Threads, hThreadArray, TRUE, INFINITE);


        // Free all the dynamically allocated structures
    }
    }
   return ret;

}

Your point 2 just isn't true. 您的观点2是不正确的。

For a regular magnetic disk, the best access pattern are big sequential reads, without having to skip back and forth due to multiple threads contending the disk time (making it waste time in seeks); 对于普通磁盘,最好的访问方式是大的顺序读取,而不必因多个线程争夺磁盘时间而来回跳过(这浪费了寻道时间); also, sequential reads play well with the read-ahead caching done by the operating system and the disk itself. 同样,顺序读取可与操作系统和磁盘本身进行的预读缓存一起很好地发挥作用。

You may want multithreading just to process the data you read from disk, but given that on a modern PC your processor is way faster than the disk for such a task, your task is going to be IO bound. 您可能只想使用多线程处理从磁盘读取的数据,但是鉴于在现代PC上,您的处理器要比磁盘快得多,因此该任务将与IO绑定。 If I were you I'd just have a single thread doing asynchronous sequential IO in big chunks (think 4 MB of data a time), encrypting the data while waiting for the disk to do its thing. 如果您是我,那么我将只有一个线程大块地执行异步顺序IO(一次想4 MB的数据),在等待磁盘执行其操作时对数据进行加密。 Another possibility is to do essentially the same thing with two threads (one doing the IO, one encrypting) and synchronous IO. 另一种可能性是使用两个线程(一个执行IO,一个加密)和同步IO进行基本相同的操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM